Skip to content

Commit 5d2935a

Browse files
docs(devpath): merge-driver comments say system-context.mdx has a generated register again, and why neither census page is routed (#26610)
<!-- claude-projects-attribution: {"github_login":"os-warren"} --> _Requested by **Warren** · [project thread](https://claude.ai/code/project/chan_01U5RdnAAmkSQmZbqh6FtqZ8?thread=cmsg_01U5RdnAAmkSQmZbqh6FtqZ8FiD8VYiNjD9zPG48Gh7MbM)_ Fixes #26535 Clause-②: no Metadata-protocol: none ## 维护者速读 - 改了什么:只改注释。`.gitattributes`、`scripts/regen-artifacts.mjs`、`scripts/git-merge-regen.mjs` 里说 `system-context.mdx`「没有生成内容」「`--fix` 会改 `file:line` 锚点」的几段注释,改成现在的事实:这页自 #26442 起有一个生成区(site register,由 `check-system-context-census.mjs --write` 重建),`tenant-audit-census.mdx` 也有一个生成区,两页都不走合并驱动,原因写进 `NOT_DRIVER_MANAGED` 那一条。 - 为什么改:#26522 让这页重新有了生成区,但三处注释还说它是纯手写文字,下一个读注释的人会据此做错判断(比如以为合并后不用跑 `--write`)。卡片还要求在同一个 PR 里决定这两页要不要交给合并驱动:结论是不要,理由已写进代码注释。 - 风险与回滚:零行为变化,没有改任何路由、脚本逻辑或发布内容;`git check-attr merge` 对两页仍答 `unspecified`。回滚即 revert。 - 先看:`scripts/regen-artifacts.mjs` 中 `content/docs/permissions/**` 条目的 `why`(不路由的四条理由);其次 `.gitattributes` 第 97 行起的那段;最后 `scripts/git-merge-regen.mjs` 的 `MIXED_COMPARATORS` 注释。 - 两分钟验证:`git check-attr merge content/docs/permissions/system-context.mdx content/docs/permissions/tenant-audit-census.mdx`,预期两行都是 `merge: unspecified`(路由没变)。 - 需要你做的:无,席位落地。 ## What changes Comments only, in three files. No routing, no code path and no published file changes. 1. **`.gitattributes` (the block from L97):** no longer says "nothing on it is generated" / "It text-merges like its prose neighbours now". It now tells the history through #22927 (which removed this row and `gen:system-context-census`), then says #26442 gave the page a generated site register again (rebuilt by `node scripts/check-system-context-census.mjs --write`). It also says the page stays unrouted, like `tenant-audit-census.mdx`, and that each page's gate catches a merge that leaves its region wrong. 2. **`scripts/regen-artifacts.mjs`, the `NOT_DRIVER_MANAGED` `content/docs/permissions/**` entry:** the `why` no longer calls every page in the directory hand-written prose. It names the two MIXED pages and their `--write` commands, and records the routing decision with its reasons (below). Its last sentence used to say "Should a generated page arrive here, route that FILE", which the two unrouted mixed pages contradicted. It now says "a page generated WHOLE". The same file also had two passages that repeated the stale claim, and the new entry would have contradicted them: the `mixed` header paragraph ("its last generated half") and the retired-row comment ("Nothing on it is generated"). Both now point to the entry. 3. **`scripts/git-merge-regen.mjs` `MIXED_COMPARATORS`:** no longer says `check-system-context-census.mjs --fix` rewrites `file:line` numbers. That flag is retired: it refuses with exit 2 and names `--write` (`scripts/check-system-context-census.mjs` header, section "`--fix` is retired"). The comment now says the comparator was written for that page's old line anchors, is the identity on the page today, and is carried by no row. It also says the marker-region register is something this comparator does not blank. In the same file, `deferralIsLossless`'s case 1 said "numbers `--fix` will re-derive" and "24 of the last 25 main commits" in the present tense. It now says the row's `gen:` re-derives the half, and gives the 24-of-25 figure as the measurement taken back then. ### Bounded in-place fix, declared The two extra passages in `scripts/regen-artifacts.mjs` and the `deferralIsLossless` sentence in `scripts/git-merge-regen.mjs` are outside the three locations the card names. All three are in files the claim already covers, have the same defect (a comment saying the page has no generated half, or that `--fix` re-derives it), are comment-only, and are read by the same gates. Leaving them would have made each file contradict itself. ## Why — the routing decision: record why not (no routing) Card's Wanted: "Decide in the same PR whether `system-context.mdx` (and `tenant-audit-census.mdx`) should be routed through the regen driver now that part of each is generated, or record why not in item 2's reason." **Decision: not routed. The reason is recorded in item 2's `why`.** Evidence, measured on `origin/main` 9dc8fba: - **A whole-side deferral would drop prose.** Both pages are hand-written prose around one region between BEGIN/END GENERATED markers. `system-context.mdx` has its register at L517–654 of 661 lines. `tenant-audit-census.mdx` has its region at L230–319 of 319 lines. An unconditional `merge=os-regen` row keeps OURS whole, which is the exact failure #14064 measured on this page. - **The `mixed` limb would buy nothing.** The only comparator is `line-anchors` (`blankAnchorLineNumbers`). Measured on both pages: `extractLineAnchors(page).length === 0` and `blankAnchorLineNumbers(page) === page`, so it is the identity. With it, `deferralIsLossless` defers only when THEIRS is byte-equal to the ancestor or to OURS. Every real edit, register-only ones included, would take `textMergeInPlace`, which is the same text merge git does today, plus a pre-commit regeneration debt. A comparator that blanks a marker region does not exist. - **No `gen:` script exists.** A `REGEN_ARTIFACTS` row needs a `gen:` and `check:` pair in its owner manifest, and the self-test verifies the names. Root `package.json` has `check:system-context-census` and no `gen:` for either page. #22927 removed `gen:system-context-census`, and the tenant-audit census has no manifest script at all; its gate runs straight from `lint.yml`. Routing would mean adding scripts, which goes beyond this card's comment-only scope. - **The driver is local.** GitHub's server-side merge and the merge queue run no custom driver (AGENTS.md, Multi-agent discipline §11), so routing would not change the merges where a conflict blocks a PR. - **The page does not lose merges unrouted.** Git text-merges both sides' prose. The register has one line per symbol and no total, so two read-adding branches change different lines. A merge that leaves either region wrong turns its gate red: `check-system-context-census.mjs` section F holds the register byte-equal to `--write`'s output, and `check-tenant-audit-census.mjs` check A does the same for its region, masking only the dated corpus-scale rows. Both gates run in `lint-repo-tooling`, behind the required `Lint & Repo Gates`, on `pull_request` and `merge_group`. `scripts/check-system-context-census.mjs`'s own header already says the page "is still not `merge=os-regen` routed: like `tenant-audit-census.mdx`, it text-merges". Routing would change merge behaviour beyond this card's comment-only path. Nothing measured here argues for it, so it is not proposed. ## Tests No behaviour changed, so no test was added and no ablation applies. The edited scripts' own suites: `pnpm check:merge-driver` (`git-env`, `git-merge-regen` and `check-regen-pending` `--self-test`; the `git-merge-regen` self-test reconciles `scripts/regen-artifacts.mjs`) ran with exit 0. `node --check` passes on both scripts. The two `packages/spec` test files that name these scripts mention them only in comments, so they are not owed. Census gates, run on the base tree and unchanged by this diff: `node scripts/check-system-context-census.mjs` exit 0, ending "the generated register (132 symbol(s)) matches the tree." `node scripts/check-tenant-audit-census.mjs` exit 0. ## Verification Head `07bd64c8`. Local subset from `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` (38 families), reconciled with `--ran`: "38 derived famil(ies) accounted for — 34 run, 4 NOT-MEASURED". <details><summary>Local gate readings (exit codes captured before any pipe)</summary> - 34 families exit 0. Among them: `check:merge-driver`, `check:nul-bytes`, `check:entry-guard`, `check:scripts-symbol-anchors`, `check:ratchet-remedy-authority`, `check:cross-package-test-inputs`, `check:ci-filter-parity`, `check-self-test-wired` (scan and `--self-test`), `check-declaration-mirrors` (scan and `--self-test`), `check-comment-mask-corpus`, and `check:pm-dispatch-gates`. That last one ran detached as its header requires and ended "dispatch-gates self-test (fast tier): 1935 cases pass". Its exit code came from the log's pass line, with no ELIFECYCLE line. - NOT MEASURED (exit 3, PREREQUISITE NOT MET: no `dist/` without a full `pnpm build`): `check:dts-closure`, `check:dual-build-cjs-loads`, `check:lean-entry-closure`, `check:sourcemap-no-sources-content`. This is a declared narrowing. These gates read built `dist/` output, which a comment edit in root `scripts/` and `.gitattributes` cannot change. CI's `Lint & Repo Gates` runs them on a fresh build. </details> `pnpm lint` and every family outside the derived list are left to CI. ## Acceptance notes - `scripts/doc-line-anchors.mjs`'s header ("Today, since #15921") still says the `'line-anchors'` comparator is "selected by that page's `mixed` field" and that the census `--fix` "regenerates only the page's declared counts". Both stopped being true at #22927. This is the same stale-comment family, but outside this card's file list, so it is left for the seat. - `scripts/regen-artifacts.mjs`'s `docs/audits/**` entry calls the strictness ledger's `.counts.md` "The ONE exception". But `docs/audits/2026-08-tenant-audit-write-call-sites.counts.md` is also generated whole (by `scripts/tenant-audit-census.mjs --write`) and unrouted, and its own header explains why. Same family, outside this card. ## Human Minimum - [x] 1. Schemas start as Zod; `packages/spec` holds no runtime logic. (n/a: no schema touched.) - [x] 2. Every name I added uses the casing for its kind. (n/a: no names added.) - [x] 3. No formatter ran; `pnpm lint` passes. (No formatter ran; `pnpm lint` is CI's.) - [x] 4. One issue, one branch off an up-to-date `main`, one pull request. - [x] 5. A change that publishes carries a changeset, and both declaration lines are filled in here and in the changeset. (Publishes nothing: root `scripts/` and `.gitattributes`, so `skip-changeset`.) - [x] 6. `packages/spec` touched: its generated artifacts are regenerated and committed. (n/a) - [x] 7. No hand edits to `content/docs/references/`, `packages/*/CHANGELOG.md` or `content/docs/releases/`. - [x] 8. Title, body and comments are in English. - [x] The *Before Submitting* list in CONTRIBUTING.md is done. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01JQwxbaFpnMwgpCgneKe2qS Co-authored-by: Claude <noreply@anthropic.com>
1 parent 804a2b0 commit 5d2935a

3 files changed

Lines changed: 57 additions & 27 deletions

File tree

‎.gitattributes‎

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -95,17 +95,25 @@
9595
# the three hottest artifacts; each gate sums its shards when it reads them.
9696
#
9797
# The elevation census page (`content/docs/permissions/system-context.mdx`) was
98-
# routed here from #13646 to #22927 and is not any more: nothing on it is
99-
# generated. It joined as a `file:line` anchor table whose correct merged values
100-
# were on NEITHER side of a conflict, became a MIXED row when #14064 measured that
101-
# a whole-side deferral dropped its hand-written prose (`mixed: 'line-anchors'`),
102-
# lost its line numbers to `path#symbol` anchors at #15921, and lost its last
103-
# generated half — the census totals — to #22927's ruling. It text-merges like
104-
# its prose neighbours now. ⚠️ What still catches a merge that leaves it wrong is
105-
# `scripts/check-system-context-census.mjs`, which re-derives the census from the
106-
# tree on every PR in the required `Lint & Repo Gates` job: a read no row anchors,
107-
# or an anchor that no longer resolves. The `mixed` field and its comparator stay
108-
# for the next mixed artifact (scripts/regen-artifacts.mjs, scripts/git-merge-regen.mjs).
98+
# routed here from #13646 to #22927 and is not any more. It joined as a `file:line`
99+
# anchor table whose correct merged values were on NEITHER side of a conflict,
100+
# became a MIXED row when #14064 measured that a whole-side deferral dropped its
101+
# hand-written prose (`mixed: 'line-anchors'`), lost its line numbers to
102+
# `path#symbol` anchors at #15921, and lost its census totals to #22927's ruling,
103+
# which took this row and `gen:system-context-census` with them. #26442 gave it a
104+
# generated half again: the site register between its BEGIN/END GENERATED
105+
# markers, rebuilt by `node scripts/check-system-context-census.mjs --write`. It
106+
# stays unrouted, as `tenant-audit-census.mdx` beside it (a generated region that
107+
# `node scripts/tenant-audit-census.mjs --write` rebuilds) always has: both are
108+
# MIXED pages that git text-merges, so neither side's prose is dropped, and the
109+
# register carries one line per symbol and no total, so two read-adding branches
110+
# merge apart. ⚠️ What catches a merge that leaves a region wrong is that page's
111+
# gate, which holds the region equal to its `--write` output on every PR in the
112+
# required `Lint & Repo Gates` job (`scripts/check-system-context-census.mjs`,
113+
# `scripts/check-tenant-audit-census.mjs`). Why neither is routed is recorded in
114+
# NOT_DRIVER_MANAGED's `content/docs/permissions/**` entry; the `mixed` field and
115+
# its comparator stay for the next mixed artifact (scripts/regen-artifacts.mjs,
116+
# scripts/git-merge-regen.mjs).
109117

110118
#
111119
# #13731 enumerated this file's blind spot and closed it: `check:merge-driver` now

‎scripts/git-merge-regen.mjs‎

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -174,9 +174,15 @@ const DECLARED_WATCH_HINTS = [
174174
*/
175175
const MIXED_COMPARATORS = Object.freeze({
176176
/**
177-
* Equal modulo `file:line` anchor numbers. The generated half of
178-
* `content/docs/permissions/system-context.mdx` is exactly those numbers:
179-
* `check-system-context-census.mjs --fix` rewrites them and touches nothing else.
177+
* Equal modulo `file:line` anchor numbers. Written for
178+
* `content/docs/permissions/system-context.mdx`, whose generated half was those
179+
* numbers until #15921 made its anchors `path#symbol`; on that page it is now the
180+
* identity (`scripts/doc-line-anchors.mjs` header), and the census `--fix` that
181+
* re-anchored them is retired. No row names it today: the page left this driver
182+
* at #22927, and the site register #26442 generated on it since lives between
183+
* markers this comparator does not blank (`check-system-context-census.mjs
184+
* --write` rebuilds it). Kept for the next `file:line` mixed artifact; a
185+
* marker-region page would need a comparator of its own.
180186
*/
181187
'line-anchors': blankAnchorLineNumbers,
182188
});
@@ -298,9 +304,10 @@ function readSide(file) {
298304
* Two shapes are lossless, and they are the ones the comparator can PROVE:
299305
*
300306
* 1. THEIRS differs from the ANCESTOR only in the generated half. Then theirs
301-
* contributes nothing but numbers `--fix` will re-derive from the merged tree,
302-
* and dropping it drops nothing. This is the common case by a wide margin —
303-
* 24 of the last 25 main commits to `system-context.mdx`.
307+
* contributes nothing but what the row's `gen:` re-derives from the merged
308+
* tree, and dropping it drops nothing. It was the common case by a wide margin
309+
* when `system-context.mdx` was the routed page this was written for — 24 of
310+
* its last 25 main commits, measured then.
304311
* 2. THEIRS and OURS agree once the generated half is blanked. Then whatever
305312
* hand-written change theirs carries, ours carries too, so keeping ours keeps
306313
* it. (Two branches landing the same doc edit, or one rebased onto the other.)

‎scripts/regen-artifacts.mjs‎

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,9 @@ export const ROOT_OWNER = '@objectstack/spec-monorepo';
5454
* `mixed` is the third answer those two lists could not express. A file can be
5555
* mixed AND still belong here, when the generated half is unreachable by any text
5656
* merge (`content/docs/permissions/system-context.mdx` was the measured case, routed
57-
* from #13646 until #22927 retired the census totals that were its last generated
58-
* half; no row carries `mixed` today) — but
57+
* from #13646 until #22927 retired its census totals; the site register #26442 has
58+
* since generated on it is left to text-merge, for the reasons its
59+
* `NOT_DRIVER_MANAGED` entry records; no row carries `mixed` today) — but
5960
* then "defer" is only correct for the merges where the discarded side changed
6061
* nothing but the generated half. The value NAMES that equivalence, and
6162
* `git-merge-regen.mjs` holds the mapping from the name to the comparator; an
@@ -237,10 +238,12 @@ export const REGEN_ARTIFACTS = Object.freeze([
237238
// row with `mixed: 'line-anchors'` (#14064 measured a whole-side deferral dropping
238239
// its prose). Its generated half was its `file:line` anchors until #15921 made
239240
// them `path#symbol`, then its census totals until #22927's ruling took those off
240-
// the page with `gen:system-context-census`. Nothing on it is generated, so it is
241-
// no artifact and has no row; it text-merges like the prose around it, and
242-
// `check:system-context-census` still re-derives the census on every PR. The
243-
// measurements this row carried are in `git log -p scripts/regen-artifacts.mjs`.
241+
// the page with `gen:system-context-census`. #26442 then generated its site
242+
// register (`check-system-context-census.mjs --write`), so it is MIXED again and
243+
// still has no row: its `NOT_DRIVER_MANAGED` entry (`content/docs/permissions/**`)
244+
// records why, and `check:system-context-census` holds the register to the tree
245+
// on every PR. The measurements this row carried are in
246+
// `git log -p scripts/regen-artifacts.mjs`.
244247

245248
// #13335 / #13731. The per-skill reference index — one row per `packages/spec`
246249
// source module, rendered whole by `gen:skill-refs`. Nine tracked files today,
@@ -418,12 +421,24 @@ export const NOT_DRIVER_MANAGED = Object.freeze([
418421
path: 'content/docs/permissions/**',
419422
why:
420423
'the DIRECTORY is not what #13646 routed, and recording that is the point of this ledger. '
421-
+ 'Its pages are hand-written permissions prose. One — `system-context.mdx` — was routed as a '
422-
+ 'MIXED file from #13646 until #22927 retired the census totals that were its last generated '
423-
+ 'half; it is plain prose now and is routed nowhere. Routing the tree the way its sibling '
424+
+ 'Its pages are hand-written permissions prose, and two of them are MIXED: hand-written prose '
425+
+ 'around one generated region between BEGIN/END GENERATED markers. `system-context.mdx` was '
426+
+ 'routed as a MIXED file from #13646 until #22927 retired its census totals, and has carried a '
427+
+ 'generated site register since #26442 (`node scripts/check-system-context-census.mjs '
428+
+ '--write`); `tenant-audit-census.mdx` carries the census region `node '
429+
+ 'scripts/tenant-audit-census.mjs --write` rebuilds. NEITHER is routed, re-weighed at #26535: '
430+
+ 'a whole-side deferral would drop the other side\'s prose; the `mixed` escape would buy nothing, '
431+
+ 'since its one comparator, `line-anchors`, blanks `file:line` digits and is the identity on '
432+
+ 'both pages (measured), so every real edit would still take the driver\'s text-merge limb; a '
433+
+ 'row needs a `gen:` script its owner manifest declares, and neither page has one; and the '
434+
+ 'driver runs only in a local merge, never in GitHub\'s server-side one or the queue\'s. What '
435+
+ 'keeps them right is their gates, which hold each region equal to its `--write` output on '
436+
+ 'every PR and queue build in the required `Lint & Repo Gates` job, so a text merge that '
437+
+ 'leaves a region wrong is red, never silent; and the register carries one line per symbol and '
438+
+ 'no total, so two read-adding branches text-merge apart. Routing the tree the way its sibling '
424439
+ '`content/docs/references/**` is routed reads as symmetry and is not: that sibling is '
425440
+ 'generated whole, this one would defer every prose page to OURS and lose the other side\'s '
426-
+ 'edits silently. Should a generated page arrive here, route that FILE and leave its '
441+
+ 'edits silently. Should a page generated WHOLE arrive here, route that FILE and leave its '
427442
+ 'neighbours to text-merge, which is correct for prose and always was.',
428443
},
429444
// ── #13731: the remaining generators, one recorded disposition each ──────────

0 commit comments

Comments
 (0)