Skip to content

feat(spec): pin every export by its .d.ts declaration text, and retire the 27 signature hashes - #18971

Merged
os-elon-musk merged 4 commits into
mainfrom
claude/issue-16045-declaration-text-snapshots
Sep 18, 2026
Merged

os-elon-musk merged 4 commits into
mainfrom
claude/issue-16045-declaration-text-snapshots

Conversation

@os-elon-musk

Copy link
Copy Markdown
Collaborator

Fixes #16045

Clause-②: yes (widening)

Ruled at 5560224701 (director batch #60, 2026-09-06, maintainer verbatim 「同意」), re-affirmed by triage at 5724532096: option A, a readable declaration-text snapshot, ⛔ not a hash. The card body's three mutually exclusive routes predate that ruling and were not re-litigated here.

@objectstack/spec pinned its public surface on one axis. api-surface/ records each export as name (kind), and a signature change, a renamed interface field and a dropped union member move none of those rows. The only shape pin was api-surface-signatures.json: 27 rows, and reference-level even there. This adds api-surface-declarations/, the declaration text the packed build actually emits for every export of every published entry point, and retires the 27 hashes it subsumes.

The counts, re-derived on this head before the first generation

The ruling asks for this by name; the card's own numbers were self-declared unverified and 12 days old.

Number Card This head (b33898f5d) Unit, and what would make it something else
entry points 17 17 type entry points in the exports map — those whose require.types ends in .d.ts. Adding or removing one such subpath.
exports map entries (not stated) 19 every key in the map. The extra two are ./openapi.json and ./package.json — asset subpaths with no declaration at all, filtered out by the same .d.ts test build-api-surface.ts has always applied. ⇒ premise 1 resolved: 17 is right and the map did not grow; 19 counts two things that were never entry points.
pinned rows 5309 5336 name (kind) rows summed over the 17 api-surface/ shards. +27 since the card. Ratio unmoved: 27/5336 = 0.51%, so the headline 99.5% stands.
distinct exported names (not stated) 5200 (entry, name) pairs. The gap to 5336 is dual-declared names, which are two rows by design.
signature hashes 27 27 top-level keys of api-surface-signatures.json. Bright control: the first value really is a sha256: string, so this counts signature entries and not empty objects.

Premise 3 also holds: all 17 packed .d.ts files exist and resolve through the map (3,215,437 bytes for the root entry down to 13,081 for ./integration). No entry point lacks a packed declaration, so the gap the dispatch reserved for itself did not open.

What the artefact costs — premise 4, which nobody had costed

shards 17, one per entry point
declaration blocks 5336
bytes 12,661,943 (12.08 MiB)
lines 237,706
gzipped 1,071,825 (1.02 MiB) — against this package's ~17.57 MiB compressed dist, so about +5.8% of tarball
largest shard system.txt, 3,592,701 bytes / 73,283 lines
median declaration 81 bytes
skew the 20 largest declarations hold ~65% of all bytes; four exceed 20,000 lines each (EnvironmentArtifactSchema 21,868, ObjectStackDefinitionSchema and ObjectStackSchema 21,851, ChangeSetSchema 20,395)

Stated plainly, as the dispatch asks, and ⛔ not as a veto: the packed .d.ts is a tsup dts rollup, so a Zod schema's declaration is its fully expanded structural type. That expansion is exactly what makes an inner field rename visible — and it is also why a single schema can produce a 21,000-line diff. The ruling's stated reason for choosing text over a hash is that the contract-review seat reads the diff; that reasoning holds per declaration and is worth a second look at the top twenty. One reading, for whoever wants it: 31% of declarations hold 97.7% of the bytes, so nothing cheap is available by trimming the tail.

Both instruments, measured on one tree at one commit

The card's thesis is that the old pin cannot fail on a shape change. Not argued — ablated, with the mutation proven on disk by blob hash and the mutation proven to have reached dist/ before any verdict was read.

A. the source-level control — a renamed interface field, the card's own class. JobRunOutcome.reason? renamed to degradationReason? in packages/spec/src/contracts/job-service.ts (blob 363443e2 to d4b1520c), spec rebuilt, ablation-dist-preflight exit 0 confirming the marker reached the built artefact:

check:api-surface              exit=0    "public API surface unchanged"      [BLIND]
check:api-surface-declarations exit=1    "~ JobRunOutcome (interface)"       [SEES IT]

Restore leg: blob back to 363443e2, rebuilt, ablation-dist-preflight --absent exit 0 (marker gone from all 214 built files), git diff HEAD clean, gate back to exit 0.

B. the gate can fail on its own artefact. One field renamed inside qa.txt by hand (blob 3f5efb04 to 5b86fec2, injected occurrences 1, deleted text 0): exit 1, attributed to TestSuiteSchema (const), failure text naming the regenerate command. Restored to the HEAD blob, git diff HEAD empty: exit 0.

The retirement, and the coverage proof the ruling demands

All 27 signature names resolve to a declaration block in api-surface-declarations/root.txt, 0 missing — enumerated from defineAction through defineWebhook, each as (function).

One honest qualification, because the subsumption is not uniform. For those 27 factory declarations the text is declare function defineAction(config: z.input of ActionSchema): ActionParsed; — a type reference, exactly as blind to an inner-key narrowing as typeToString was. What is gained is not sharper text on the 27; it is the 5309 other declarations, including ActionSchema itself, whose own expanded block is where such a narrowing shows up. So the retirement is a strict superset of pinned declarations, not an equal trade. Nothing published read the retired file — it was never in this package's files[].

Where it lands, and why there

  • Generator: packages/spec/scripts/build-api-surface-declarations.ts, beside the eight sibling artefact generators, reading the same input through the same collectEntries logic. The ruling says "one generator script under scripts/"; this reads that as the directory the whole family lives in, because the artefact reads the built dist and only the lane that builds spec can run its gate.
  • Artefact: packages/spec/api-surface-declarations/ENTRY.txt, a sibling directory of api-surface/. Not inside it: listShardNames throws on any file in that directory that is not a NAME.json shard, so api-surface/ is closed by construction. No existing api-surface/*.json is regenerated by this PR (check:api-surface green throughout), which keeps it clear of PR feat(spec)!: a structured region body refuses a pause-capable node and an 'end' node #18688 and PR feat(spec)!: manifest.id enforces the reverse-domain rule its registry face already had #18319.
  • Gate: check:api-surface-declarations, a step in lint.yml's Type Check · consumer gates lane after the two build steps, with check:api-surface and the other dist-reading gates. No new required context — a step in an existing lane. Registered in the check:generated ledger, in REGEN_ARTIFACTS, and in .gitattributes as merge=os-regen.
  • Sharded per entry point from day one, for the reason its neighbour is: the merge queue rebuilds server-side where no custom driver runs, so two PRs sharing one generated file evict the second. Pit 1 from 5715457322 is answered by the layout rather than by an assumption — and check:merge-driver, which reconciles .gitattributes against REGEN_ARTIFACTS in both directions, is green over the swap.
  • Published, with the reason the gate demands. check:published-files refuses a files[] entry that carries none; the registered line says what a consumer does with it — read two published tarballs and see which declared shape moved between releases, the question api-surface cannot answer. If 1.02 MiB of tarball is judged too much, one line of files[] removes it without touching anything else.

Three registries had to learn about the new gate, each because it discovered the gate on its own rather than because a list named it:

  • check:published-files — demanded the reason above.
  • scripts/pm/dispatch-gates.mjs — its live manifest edge gave the new gate a population before anything listed it, which is the eighth member of a class whose seventh was recorded the same way. Declared as CLASS_EIGHTH, with a case asserting the edge really reaches it.
  • scripts/pm/check-widening-tells.mjsPUBLISHED_SURFACES is derived from REGEN_ARTIFACTS, so retiring the signatures row dropped it off that surface and reddened two self-test cases. Both are retargeted to state the retirement as a counterfactual (the surface follows the table, not a literal); ⛔ the new artefact is not added to that surface, because the ruling assigns "is a snapshot diff a Clause-② signal" to the skills seat by name and out of this card's scope. Both directions are now pinned, so the boundary is declared rather than forgotten. 483 cases pass, up from 481.

Verification

  • Gate families: derived with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands from the merge base, 120 commands, every exit code redirected to a file and read back. All 120 green. Four returned exit 3 PREREQUISITE NOT MET on first pass (check:doc-formula-expressions, check:dual-build-cjs-loads, check:lean-entry-closure, check:type-check-debt); each names a build, each was built and re-run green, and none is recorded as a finding. Reconciled with --ran.
  • Tests: @objectstack/spec local project 488 files / 14,182 tests passed; the tooling suites that name the edited scripts, both projects, 10 files / 220 tests passed (sharded-artifacts, check-generated-ledger, dist-freshness, dist-freshness-adoption, api-surface-dual-kind-rows.pin, build-schemas-check-mode, def-key-collisions, root-index, export-list, docs-import-surface). pnpm --filter @objectstack/spec typecheck green.
  • eslint, the union rather than a narrowing: eslint . --no-inline-config --format json at b33898f5d examined 6856 files, 0 errors, 0 warnings, exit 0. The population is eslint's own config resolution and the count is read from its JSON output; type-aware linting is not enabled in eslint.config.mjs (no parserOptions.project, no typed rules), so this diff cannot move an untouched file's verdict either way.
  • Control bytes: check:nul-bytes green over 8906 files, plus a direct scan of all 31 changed paths for the wider control-byte class — no matches.
  • scripts/check-single-claim-paths.mjs in the diffstat is not mine: it arrived with the one-commit origin/main merge (16cb493d5) this PR carries.

Acceptance notes

维护者速读(草稿)

改了什么。 @objectstack/spec 从今天起为它的每一个公开导出留一份"形状快照" —— 不是哈希,而是打包后 .d.ts 里那段声明原文,按入口点分成 17 个文件签入仓库,并配一道 CI 闸门:重新生成后对不上就红,失败信息里直接给出重新生成的命令。同时退休了旧的 27 条签名哈希文件。

为什么改。 原来的 pin 只记"某个名字还在不在",5336 行里只有 27 行能看出"形状变没变"。也就是说:把一个接口字段改名、砍掉一个联合成员、改一个函数签名 —— 这些都是会让客户升级后编译失败的破坏性改动 —— 全部一路绿灯。本次 PR 里有实测:改了 JobRunOutcome 的一个字段名之后,旧闸门 check:api-surface 退出码 0(看不见),新闸门退出码 1(点名了那个 interface)。路线是 2026-09-06 决策批次 #60 里您逐字「同意」的那一条。

风险与代价(含回滚)。 代价是体积:12.08 MiB 文本、23.7 万行,压缩后 1.02 MiB,相当于 npm 包增长约 5.8%。更值得注意的是分布极不均匀 —— 最大的 4 个 schema 各自超过 2 万行声明文本,一旦它们变动,复核席位面对的是一份 2 万行的 diff;而裁决选"文本不选哈希"的理由恰恰是"diff 可读"。这一点我按实测如实报告,未自行改动路线。回滚成本很低:从 files[] 去掉一行即可停止随包发布;整道闸门回滚就是撤销本 PR,不留任何数据迁移。

席位意见。

你要做的。 只有一件事需要您判断:12 MiB / 23.7 万行这个量级,以及最大 4 个 schema 的 diff 可读性,是否仍符合当初选 A 方案时的预期。若认为需要收窄,那是裁决层面的一次增补,不是本 PR 的返工。其余部分已按裁决落地并自证。


Generated by Claude Code

@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

⚠️ 19 changed file(s) yielded no anchor (packages/spec/api-surface-declarations/ai.txt, packages/spec/api-surface-declarations/api.txt, packages/spec/api-surface-declarations/automation.txt, …), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files. Nothing else in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 1 changed package(s)).

What this run could not see
  • 19 changed file(s) yielded no anchor (packages/spec/api-surface-declarations/ai.txt, packages/spec/api-surface-declarations/api.txt, packages/spec/api-surface-declarations/automation.txt, …) — pages documenting those are invisible to this run
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.

Coarse fallback — 136 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 89c6ec52b56a24d94c5bdea57fb8a7a8db4273dapackageMentionDocs.

@github-actions github-actions Bot added ci/cd dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation tooling labels Sep 18, 2026

Copy link
Copy Markdown
Collaborator Author

Test Core (1/6) failed on this head — measured, and the single re-run is being held deliberately

Failing check: Test Core (1/6), head b33898f5d8d0dc8eff732eb8ac26452506b8622e, job 105540309254, read 2026-09-18T0854Z.

The failure itself, from the job log:

FAIL packages/qa/vitest-filter-preflight/test/config-wiring-sweep.test.ts
     > packages/cli/vitest.config.ts
     > ⭐ CONTROL — refuses NOTHING when no override is named
Error: Test timed out in 5000ms.   (test/config-wiring-sweep.test.ts:306:3)
Test Files  1 failed | 2 passed (3)
     Tests  1 failed | 110 passed (111)

Why this is very likely not this pull request's

Measured on the diff rather than assumed:

  • The 31 changed files contain 0 files under packages/qa/**, and 0 changed paths matching vitest. Lit control on the same instrument: 23 changed files under packages/spec/, so the zero is a real absence and not a dead query.
  • The failing subject is packages/cli/vitest.config.ts, which this diff does not touch either.
  • The failure is a 5000ms timeout on a test that spawns a real vitest child process. In the SAME run, the same-named ⭐ CONTROL leg passed for other configs at 2098ms and 1442ms — so this family habitually runs at roughly 30–40% of its own limit, and a loaded runner crossing 5s is the timing shape rather than a behavioural change.
  • 110 of 111 tests in that package passed.

Two grounds I checked and did NOT get to rely on, stated so this is not read as hand-waving

  • Not red on the base branch. On main tip 89c6ec52b5, Test Core (1/6) is success, and main has 0 failing checks. The "red on base too" limb does not hold here.
  • It did not pass earlier on this exact commit. There is exactly one run of that check name on this head. The names with repeated runs on this head are Auto Label, Check PR Size, Packed-tarball smoke (opt-in) and Check Changeset — not Test Core.

So the only remaining ground for "not this PR's" is that it reproduces identically on one re-run, and that re-run has not been spent.

Why the re-run is being held rather than fired now

At the time of reading, 16 checks were still in progress on this head. The standing rule allows at most one re-run in total, so spending it on a single job while other jobs could still fail would waste it. It is held until the run converges, then spent once across the whole failure set.

⛔ Not done and not on the table: skipping, disabling or quarantining the test; an empty commit or a close/reopen to kick CI; editing the check.

One more reading worth recording

The same job log shows @objectstack/spec:test was scheduled but never reached — "the run stopped before it" — along with 10 other packages (check-test-completeness: OK (1 of 12 scheduled package(s) reported … 11 never reached)). This shard therefore has not yet exercised this pull request's own package at all, so it is no evidence either way about the change itself.

What happens next

  • Re-run reproduces identically ⇒ the failure is not this PR's by the standing definition, and the timeout gets its own card rather than being ignored: whoever finds a flake fixes it or files it, never routes around it.
  • Re-run passes ⇒ flake confirmed on a timing-sensitive subprocess test, and it still gets that card, because a green re-run is not a root cause.

Either way this PR is not landed on a red head, and the contract review for it is proceeding separately.


Generated by Claude Code

os-elon-musk commented Sep 18, 2026

Copy link
Copy Markdown
Collaborator Author

Contract review

Served-tier: 88/88 CONTRACT_REVIEW_TIER
Head-sha: b33898f5d8d0dc8eff732eb8ac26452506b8622e

Tier was verified from the reviewing subagent's OWN transcript, not from its self-report: 88 per-turn model stamps read, all 88 equal to the constant above, zero stamps of any other value. A subagent cannot self-attest, because its get_session reads the parent session rather than itself. This seat serves below that constant, which is why the review was routed to an isolated subagent instead of being done in seat.

① Derived judgments

The ruling (5560224701, director batch #60, maintainer verbatim 「同意」) required a readable declaration-text snapshot of every export of every published entry point, ⛔ not a hash. Independently re-measured by the reviewer against the branch blobs:

  • Text, not a hash. First-token histogram over all 5,336 blocks: type 2,376 · declare const 2,076 · declare function 447 · interface 430 · declare class 7; 0 blocks fail to start with a declaration keyword, 0 (other)/(namespace) kinds, 0 inline import(...) types. No digest anywhere in the artefact or the check path — the verdict is a byte compare of regenerated against on-disk shard text.
  • Coverage is total and symmetric. Per-shard set comparison of the api-surface JSON rows against the api-surface-declarations text markers, shard by shard: all 17/17 shards show only_json = 0 and only_txt = 0; totals 5,336 rows = 5,336 blocks. collectEntries() in the new generator is byte-identical to build-api-surface.ts's, so both artefacts agree on the 17 entry points and exclude the two asset subpaths identically.
  • The retirement drops no signal — the load-bearing claim, re-verified rather than accepted. All 27 signature-hash entries of the deleted api-surface-signatures.json (read from origin/main) were checked against the branch's root.txt: 27 hit, 0 miss, each block's first line carrying the full declare function signature. Lit controls: the fixture's fake name defineWorkflow → 0; defineAction sought in the wrong shard → 0; total markers in root.txt → 213 (must-hit). The new instrument additionally covers 8 define* functions outside root that the old root-only, functions-only hash never saw.
  • Both directions of the new gate. The retired instrument hashed checker.typeToString(...) — reference-level, root only, functions only. The new one records the same 27 nodes' declaration text, which strictly contains that signature information, so anything that moved the old hash moves the new block. Ablation A (source rename JobRunOutcome.reason?degradationReason?, rebuilt, both gates on the same dist) tests exactly the card's thesis class through the real pipeline and shows the OLD gate blind (exit 0) while the new one reds naming ~ JobRunOutcome (interface); ablation B (hand-edited shard) tests the byte compare and the per-block attribution.
  • Classes missed by BOTH the old hashes and the new snapshot, named rather than glossed: runtime-only zod narrowing (.min(), .regex(), .refine()) leaves the printed TS type unchanged and belongs to the authorable-surface/dropped-refinements axis; values behind a widened declared type; function-body behaviour; and deliberately, leading TSDoc wording. None is a regression introduced by this retirement.
  • Reproducibility across machines. CI's own Type Check · consumer gates step "Check @objectstack/spec declaration text (the shape half)" passed on this head after CI's build steps, i.e. the checked-in shards byte-matched a dist built on a GitHub runner.

② Semver level

@objectstack/spec minor. Under the launch-window rule a purely additive widening of a published package's public surface takes at least minor, and major is refused outside pre-mode (scripts/check-changeset-no-major.mjs), so minor is both floor and ceiling here. The PR body's line-initial Clause-②: yes (widening) and the changeset's backticked form were traced through the one shared parser (readClause2Line, imported by both check-changeset-no-major.mjs and check-adr-0087-registration.mjs): both read declared / yes / widening. Check Changeset is success on this head.

③ Boundary flags

  • Clause-② arm: widening, declared line-initial on both carriers, which agree.
  • Governed surface: nonecheck-governed-merges.mjs --pr 18971 derived 31 paths three-dot and hit 0 of 5 surfaces, exit 0. Ordinary queue landing applies; no human approval is owed for this PR.
  • Release-owned surface: untouched — 0 files under content/docs/releases/, control 23 under packages/spec/.
  • Generated-artefact registration: both the .gitattributes merge=os-regen row and regen-artifacts.mjs's REGEN_ARTIFACTS row were swapped from the retired file to the new directory, with a check-generated.ts GATED ledger row; 30 residual mentions of the deleted file are all prose, CHANGELOG history, negative test cases or two acknowledged stale comments.
  • ⚠️ Publication exceeds the ruling's letter. The ruling says "a checked-in snapshot beside api-surface/*.json" and says nothing about files[] or the npm tarball; the one files[] line is what makes this a Clause-② event at all. Reviewer measurement added on top: nothing in-repo reads a published api-surface-declarations/ today (release-spec-changes.sh reads only package/api-surface), so the +1.02 MiB gzipped (+5.8% of tarball) ships for a consumer that does not yet exist. This is escalated to the maintainer as an open option (drop the one files[] line) and is not resolved by this PASS.
  • ⚠️ The ruling's own follow-up is not in place. PUBLISHED_SURFACES is REGEN_ARTIFACTS.filter(row => row.check === 'check:api-surface'), so the new artefact is off that surface by construction and nothing yet turns a snapshot diff into a Clause-② carrier automatically. The ruling assigned that input row to the skills seat by name and out of this card's scope; filed as ruling 5560224701 assigned a contract-review input row naming the snapshot diff as a Clause-② signal, and nothing carries it #18976 so the assignment has a carrier.
  • ⚠️ One claim in this PR over-reaches its mechanism. Header, changeset and docblock all say a declaration's leading TSDoc is excluded. True of the LEADING comment only: member-level JSDoc inside interface/object bodies IS recorded — 403 blocks contain /**, 8,853 comment lines, 3.7% of the artefact. Consequence once the snapshot becomes a Clause-② signal: doc-only edits will red the gate and summon contract review. Non-blocking, but the claim should be amended or member comments stripped.
  • Artefact-stability facts for the record: 237,723 lines but only 40,806 unique (5.83× expansion); top 20 blocks hold 64.5% of bytes; four blocks exceed 20,000 lines; 24% of blocks print zod-internal names, so a zod or TypeScript emitter upgrade can rewrite a quarter of the artefact with zero source change.

Carrier clear

Both carriers are cleared on the strength of this record, in the protocol's order — record first, then the strip, so the gate is never open-with-nothing-behind-it: PR #18971 and card #16045. ⚠️ Correction to this record, made by its author. As first posted, this paragraph cited a comment id for "the full reviewer report". That id does not exist on this pull request: the isolated reviewer returned its report to the dispatching seat as an in-session hand-back, which is not a GitHub artefact, and the id was mistakenly written as though it were one. No such comment was ever posted here. The three comments on this pull request are the docs-drift check, the Test Core (1/6) note, and this record. This record is therefore the durable carrier of the review, and every reading quoted above is reproduced here rather than pointed at.

The reviewer's per-item verdicts, for audit:

item verdict
1 Faithfulness to the ruling PASS
2 Retirement of the 27 hashes PASS (27 hit / 0 miss, 3 lit controls)
3 New gate catches both directions PASS
4 Widening arm, semver level, carrier consistency PASS WITH FINDINGS
5a Generator location PASS, declared-and-sound
5b Published in files[] PASS with the finding above
5c Not on PUBLISHED_SURFACES PASS — the ruling says so verbatim
5d Three contended files PASS — holder #18948 already merged, merge-tree 0 conflicts
6 Artefact size reading, no verdict — maintainer's disposition
7 Generated-artefact registration PASS
8 Release-owned surface PASS
9 Adversarial read of the generator PASS with findings

Reviewer-declared instrument failures, carried rather than hidden: the Actions job-logs endpoint returned 403 through the proxy, so the new gate's CI result was bound through the job's steps array instead of log text; a first statistics script crashed after printing its top-20 table, so the redundancy and overload figures come from a corrected second run over the same extracted blobs; a noisy "identifiers referenced without a block" heuristic was discarded and used for no verdict; the gzip figure differs from the author's by under 4% by method; and with no dist/ in the shared checkout, the packed .d.ts could not be inspected for non-exported helper types, which is stated as CANNOT-DETERMINE and is load-bearing for nothing above.

CI on this head at 2026-09-18T0924Z: 31 success, 5 skipped, 0 failures, all converged, every run bound to this head. The earlier Test Core (1/6) failure was a timing flake in packages/qa/vitest-filter-preflight — a package this diff does not touch (0 of 31 files; lit control 23 under packages/spec/) — and its re-run passed at 09:22:36Z. It is filed separately rather than waved through.

Implemented-by: claude/issue-16045-declaration-text-snapshots
Reviewed-by: session_019srGWGCBBCBHqcDoRZpQRh

VERDICT: PASS


Generated by Claude Code

@os-elon-musk
os-elon-musk marked this pull request as ready for review September 18, 2026 09:27
@os-elon-musk
os-elon-musk added this pull request to the merge queue Sep 18, 2026
Merged via the queue into main with commit d8b12fc Sep 18, 2026
64 of 66 checks passed
@os-elon-musk
os-elon-musk deleted the claude/issue-16045-declaration-text-snapshots branch September 18, 2026 09:53
os-elon-musk pushed a commit that referenced this pull request Sep 18, 2026
…/main

The declaration-text pins main brought in #18971 move with this branch's two
facts: `source` becomes required wherever the predicate contract composes, and
`cel` / `expression` now declare the `EvaluatedExpression` they always emitted.
Exactly 8 distinct changed lines across all six files; the line count is those
two facts repeated at every composing site.

Claude-Session: https://claude.ai/code/session_019srGWGCBBCBHqcDoRZpQRh
Co-authored-by: Claude <noreply@anthropic.com>

Copy link
Copy Markdown
Collaborator Author

Maintainer ruling C — this PR is being reverted (skills seat, session_01BTeBejoPUvRHN8WdAJC6oF) · 2026-09-18T11:39Z

Recorded verbatim on #16045 (the card this PR closed): the maintainer read this PR's size and review trail with the skills seat and chose, of three options, 「C」 — revert, and make consumer compilation against spec@main the shape gate. Carriers: the revert is objectstack #19011 (domain:spec, p1; git revert d8b12fca9 applies cleanly on main, 31 files, 119 / 238,310; it lands by the maintainer's hand under the new 5,000-line human-merge rule, #19012); objectui's compile gate is objectui #9860. ⛔ Nothing here is a finding against the dev or the spec seat: the ruling this PR executed (5560224701) was the maintainer's, and the reversal is too.


Generated by Claude Code

@os-elon-musk
os-elon-musk restored the claude/issue-16045-declaration-text-snapshots branch September 18, 2026 12:01
os-steve pushed a commit that referenced this pull request Sep 20, 2026
…napshot

Resolves 13 modify/delete conflicts under packages/spec/api-surface-declarations/.

Every conflict has the same shape: this branch deletes the file (no stage 2),
main regenerated it (stage 3). Retiring that directory is the revert's whole
purpose, so each conflict resolves to the delete. All 17 shards are gone from
the merged tree -- the 4 main did not touch auto-resolved to delete already.
The one other overlapping path, scripts/pm/dispatch-gates.mjs, auto-merged:
main's hunk sits about 1600 lines from the reverted one.

Verified on the merged tree rather than assumed:

- no code, script, workflow, gitattributes or package.json entry references
  api-surface-declarations in any spelling; the only three mentions left are
  historical prose in .changeset release notes (17108, 18991, 19085), reported
  separately and deliberately not edited here.
- of the 31 paths the reverted commit touched, none still carries a line that
  commit added; the four that differ from its parent are later, unrelated work
  main landed (lint.yml keeps #18889's step; check-published-files,
  dispatch-gates and regen-artifacts carry post-revert commits).
- api-surface-signatures.json is back with its 27 hashes and, built from these
  merged sources, check:api-surface reports the public API surface and factory
  signatures unchanged -- so the restored pin is correct, not merely present.
- check:generated reports all 15 artifacts up to date; main's count is 16, and
  16 is what #18971 made it when it registered check:api-surface-declarations.

Claude-Session: https://claude.ai/code/session_01AmH9bKvGoLjiY86Q4Z3og2
Co-Authored-By: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/cd dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation domain:spec size/xl tooling

Projects

None yet

2 participants