Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .gitattributes
Original file line numberDiff line numberDiff line change
Expand Up@@ -75,6 +75,23 @@
# hand-written measurement of how each type got where it is — and is NOT.
# Regenerating a Note would fabricate a verdict, which that README calls worse
# than a missing row.
#
# The elevation census page joined at #13646 — a generated `file:line` anchor
# table whose correct merged values are on NEITHER side of a conflict (measured on
# #13625: five conflicted anchors resolved to 4408/5771/6019/6382/6575 against
# branch 4407/5770/… and main 4284/5647/…), so no text merge and no hand merge can
# reach them. ⚠️ It is routed as the FILE and NOT as `content/docs/permissions/**`:
# unlike `content/docs/references/**` above, which is generated whole, that
# directory is 22 hand-written prose pages around one generated one, and the glob
# would defer the prose to OURS. See NOT_DRIVER_MANAGED for that entry.
#
# This is also the row where the header's own warning is answered rather than
# accepted: deferring is safe here because `scripts/check-system-context-census.mjs`
# still reddens on every PR from the required `Lint & Repo Gates` job — it
# RE-DERIVES the census from the tree, so it catches the stale anchors a merge
# leaves behind even when nothing conflicted, which is the majority case (#13625:
# 18 anchors stale, 5 marked). The driver removes hand-merge rounds; it is never
# the only signal.

packages/spec/spec-changes.json merge=os-regen
packages/spec/liveness/state-counts.md merge=os-regen
Expand All@@ -89,3 +106,4 @@ packages/spec/api-surface-signatures.json merge=os-regen
docs/protocol-upgrade-guide.md merge=os-regen
docs/audits/2026-07-unknown-key-strictness-ledger.counts.md merge=os-regen
content/docs/references/** merge=os-regen
content/docs/permissions/system-context.mdx merge=os-regen
4 changes: 3 additions & 1 deletion package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -146,7 +146,9 @@
"check:tenant-chokepoint": "node scripts/check-tenant-chokepoint.mjs --self-test && node scripts/check-tenant-chokepoint.mjs",
"check:stall-guard": "node scripts/run-with-stall-guard.mjs --self-test",
"check:stall-guard-budget": "node scripts/check-stall-guard-budget.mjs --self-test && node scripts/check-stall-guard-budget.mjs",
"check:stall-guard-headroom": "node scripts/measure-stall-guard-headroom.mjs --self-test"
"check:stall-guard-headroom": "node scripts/measure-stall-guard-headroom.mjs --self-test",
"gen:system-context-census": "node scripts/check-system-context-census.mjs --fix",
"check:system-context-census": "node scripts/check-system-context-census.mjs --self-test && node scripts/check-system-context-census.mjs"
},
"keywords": [
"objectstack",
Expand Down
60 changes: 60 additions & 0 deletions scripts/check-system-context-census.mjs
Original file line numberDiff line numberDiff line change
Expand Up@@ -119,6 +119,36 @@
* of zero files, a declared-count pattern that matches nothing, an UNENFORCED row
* that vanished or lost its date, and a ledger row that locates nothing are all
* exit 1 naming what could not be read.
*
* ## ⭐ Wiring, and why the self-test asserts it (#13646)
*
* This gate IS the "regenerate and diff" instrument for the page: it re-derives the
* census from the tree and reddens when the committed anchors disagree. That makes
* it the only thing standing between the page and the failure mode that has no
* other signal -- an anchor going stale because the file it CITES moved, in a merge
* that produced no conflict at all.
*
* Measured on `cc837dbfec` by shifting `plugin-sharing/src/sharing-service.ts` down
* 29 lines (main's real delta in the #13625 window) with the page untouched, which
* is the branch-never-touched-that-file case git merges clean and silent:
*
* gate on the shifted tree exit 1, 16 findings, naming every one of the five
* sharing-service anchors and the ledger row
* `--fix` then the gate 109 sites re-anchored, exit 0
*
* So the anchors are recoverable and the loss is loud -- PROVIDED the gate is
* scheduled. Nothing asserted that it was. `check-self-test-wired` is conditional
* in the wrong direction here: it requires that a script CI runs also has its
* `--self-test` run, so deleting BOTH invocations from `lint.yml` retires this gate
* with every check still green. The self-test therefore reads the workflow text and
* asserts both legs, the way `check-doc-frontmatter`, `check-aggregator-roster` and
* `check-ci-filter-parity` each assert their own -- a gate that exists and is not
* scheduled is the dormant shape seen from the other side.
*
* ⚠️ The pin deliberately needs NO workflow edit: `lint.yml` already invokes both
* legs, in the required `Lint & Repo Gates` job, on a trigger set that includes
* `merge_group` and with no `paths:` filter. It is the repo's busiest file and the
* assertion reads it rather than adding to it.
*/

import { readFileSync, writeFileSync } from 'node:fs';
Expand DownExpand Up@@ -1501,6 +1531,36 @@ function selfTest() {
refusalText
);

// ── WIRING: this gate, and its self-test, really run in CI ──────────────────
//
// ⭐ The half a clean tree cannot show, and the reason this block exists. Every
// other case above judges the RULES; this one judges whether anything runs them.
// `check-self-test-wired` is conditional in the wrong direction for that -- it
// requires "if CI runs the script, CI runs its --self-test too", so deleting BOTH
// lines from `lint.yml` leaves it green and silently retires the only instrument
// that catches a stale anchor. Measured: the census is what reddens when a cited
// file moves underneath a page nobody edited, so its scheduling is load-bearing,
// not incidental.
//
// Asserted against the workflow TEXT, following the precedent `check-doc-frontmatter`,
// `check-aggregator-roster` and `check-ci-filter-parity` set -- and, like the second
// docs root that gate added, this needed NO workflow edit: `lint.yml` already invokes
// both legs, and it is the repo's busiest file.
const SELF = 'scripts/check-system-context-census.mjs';
let lintYml = null;
try {
lintYml = readFileSync(join(ROOT, '.github/workflows/lint.yml'), 'utf8');
} catch (err) {
t(`WIRING: .github/workflows/lint.yml is readable`, false, err.code ?? err.message);
}
if (lintYml !== null) {
t(
'WIRING: lint.yml invokes this gate directly (the GATE INVOCATION IDIOM, not a package.json fence)',
lintYml.includes(`node ${SELF}\n`)
);
t('WIRING: lint.yml runs the --self-test leg too', lintYml.includes(`node ${SELF} --self-test`));
}

process.stdout.write(
failures === 0
? '\ncheck-system-context-census --self-test: all cases passed\n'
Expand Down
50 changes: 50 additions & 0 deletions scripts/regen-artifacts.mjs
Original file line numberDiff line numberDiff line change
Expand Up@@ -179,6 +179,45 @@ export const REGEN_ARTIFACTS = Object.freeze([
gen: 'gen:liveness-counts',
check: 'check:liveness',
},
// #13646. The elevation census page — a generated `file:line` anchor table, and
// the first row here owned by ROOT tooling rather than by `packages/spec` (the
// owner field #13585 added exists for exactly this).
//
// ⚠️ The row is the FILE, not `content/docs/permissions/**`, and the difference
// is safety rather than tidiness. Its routed sibling `content/docs/references/**`
// is a whole generated tree; `content/docs/permissions/` is 22 hand-written prose
// pages with ONE generated page among them, so the directory glob would hand 21
// prose files to a driver that resolves to OURS — laundering away a sibling's
// prose edit, which is the exact trade `migrations/registry.ts` is kept out of
// this table for. The glob is recorded in NOT_DRIVER_MANAGED below.
//
// Why it belongs here at all: two PRs that each ran `--fix` against their own
// tree write correct-for-themselves line numbers into the same rows, and the
// merged tree's correct values equal NEITHER side — measured on #13625's merge,
// where the five conflicted anchors resolved to `4408/5771/6019/6382/6575`
// against branch `4407/5770/…` and main `4284/5647/…`. A text merge cannot reach
// that answer from either input, so this is a deferral-and-regenerate shape.
//
// ⭐ And the deferral is safe in the direction that matters, which is the
// question `os-regen-merge.sh` raises about every path here — a driver that
// exits 0 trades a loud failure for a silent one unless something else still
// reddens. Here something does, on every PR: `check-system-context-census.mjs`
// runs in the required `Lint & Repo Gates` job with no `paths:` filter and on
// `merge_group`, it re-derives the census from the tree rather than reading the
// page back, and its scheduling is pinned by its own `--self-test` (#13646). The
// driver is therefore the cheap half here and never the only signal.
//
// No `readsDist`/`readsSchemaTree`: the census is an AST walk over `src/`, so a
// merged tree is the whole prerequisite. `gen` cannot launder a POPULATION change
// either — `--fix` re-anchors a pure shift and REFUSES when a site arrived or
// vanished, leaving the page untouched and the gate red (measured: exit 1, zero
// anchors rewritten, `[declared-count] ruling-sites says 109, the census says 110`).
{
path: 'content/docs/permissions/system-context.mdx',
gen: 'gen:system-context-census',
check: 'check:system-context-census',
owner: ROOT_OWNER,
},
]);

/**
Expand DownExpand Up@@ -238,6 +277,17 @@ export const NOT_DRIVER_MANAGED = Object.freeze([
+ 'registries and the other one is `scripts/adr-anchors.json` (#7301). Splitting this one too is '
+ 'a follow-up with its own measurement, not a rider.',
},
{
path: 'content/docs/permissions/**',
why:
'the DIRECTORY is not what #13646 routed, and recording that is the point of this ledger. '
+ '22 of its 23 pages are hand-written permissions prose; exactly one — `system-context.mdx`, '
+ 'declared above — is a generated anchor table. Routing the tree the way its sibling '
+ '`content/docs/references/**` is routed reads as symmetry and is not: that sibling is '
+ 'generated whole, this one would defer 21 prose files to OURS and lose the other side\'s '
+ 'edits silently. Route the generated FILE; leave the neighbours to text-merge, which is '
+ 'correct for prose and always was.',
},
{
path: 'docs/audits/**',
why:
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
fix(devx): route the elevation census page to os-regen, and pin the CI gate that is the real guard by claude[bot] · Pull Request #13732 · objectstack-ai/objectstack · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .gitattributes
Original file line numberDiff line numberDiff line change
Expand Up@@ -75,6 +75,23 @@
# hand-written measurement of how each type got where it is — and is NOT.
# Regenerating a Note would fabricate a verdict, which that README calls worse
# than a missing row.
#
# The elevation census page joined at #13646 — a generated `file:line` anchor
# table whose correct merged values are on NEITHER side of a conflict (measured on
# #13625: five conflicted anchors resolved to 4408/5771/6019/6382/6575 against
# branch 4407/5770/… and main 4284/5647/…), so no text merge and no hand merge can
# reach them. ⚠️ It is routed as the FILE and NOT as `content/docs/permissions/**`:
# unlike `content/docs/references/**` above, which is generated whole, that
# directory is 22 hand-written prose pages around one generated one, and the glob
# would defer the prose to OURS. See NOT_DRIVER_MANAGED for that entry.
#
# This is also the row where the header's own warning is answered rather than
# accepted: deferring is safe here because `scripts/check-system-context-census.mjs`
# still reddens on every PR from the required `Lint & Repo Gates` job — it
# RE-DERIVES the census from the tree, so it catches the stale anchors a merge
# leaves behind even when nothing conflicted, which is the majority case (#13625:
# 18 anchors stale, 5 marked). The driver removes hand-merge rounds; it is never
# the only signal.

packages/spec/spec-changes.json merge=os-regen
packages/spec/liveness/state-counts.md merge=os-regen
Expand All@@ -89,3 +106,4 @@ packages/spec/api-surface-signatures.json merge=os-regen
docs/protocol-upgrade-guide.md merge=os-regen
docs/audits/2026-07-unknown-key-strictness-ledger.counts.md merge=os-regen
content/docs/references/** merge=os-regen
content/docs/permissions/system-context.mdx merge=os-regen
4 changes: 3 additions & 1 deletion package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -146,7 +146,9 @@
"check:tenant-chokepoint": "node scripts/check-tenant-chokepoint.mjs --self-test && node scripts/check-tenant-chokepoint.mjs",
"check:stall-guard": "node scripts/run-with-stall-guard.mjs --self-test",
"check:stall-guard-budget": "node scripts/check-stall-guard-budget.mjs --self-test && node scripts/check-stall-guard-budget.mjs",
"check:stall-guard-headroom": "node scripts/measure-stall-guard-headroom.mjs --self-test"
"check:stall-guard-headroom": "node scripts/measure-stall-guard-headroom.mjs --self-test",
"gen:system-context-census": "node scripts/check-system-context-census.mjs --fix",
"check:system-context-census": "node scripts/check-system-context-census.mjs --self-test && node scripts/check-system-context-census.mjs"
},
"keywords": [
"objectstack",
Expand Down
60 changes: 60 additions & 0 deletions scripts/check-system-context-census.mjs
Original file line numberDiff line numberDiff line change
Expand Up@@ -119,6 +119,36 @@
* of zero files, a declared-count pattern that matches nothing, an UNENFORCED row
* that vanished or lost its date, and a ledger row that locates nothing are all
* exit 1 naming what could not be read.
*
* ## ⭐ Wiring, and why the self-test asserts it (#13646)
*
* This gate IS the "regenerate and diff" instrument for the page: it re-derives the
* census from the tree and reddens when the committed anchors disagree. That makes
* it the only thing standing between the page and the failure mode that has no
* other signal -- an anchor going stale because the file it CITES moved, in a merge
* that produced no conflict at all.
*
* Measured on `cc837dbfec` by shifting `plugin-sharing/src/sharing-service.ts` down
* 29 lines (main's real delta in the #13625 window) with the page untouched, which
* is the branch-never-touched-that-file case git merges clean and silent:
*
* gate on the shifted tree exit 1, 16 findings, naming every one of the five
* sharing-service anchors and the ledger row
* `--fix` then the gate 109 sites re-anchored, exit 0
*
* So the anchors are recoverable and the loss is loud -- PROVIDED the gate is
* scheduled. Nothing asserted that it was. `check-self-test-wired` is conditional
* in the wrong direction here: it requires that a script CI runs also has its
* `--self-test` run, so deleting BOTH invocations from `lint.yml` retires this gate
* with every check still green. The self-test therefore reads the workflow text and
* asserts both legs, the way `check-doc-frontmatter`, `check-aggregator-roster` and
* `check-ci-filter-parity` each assert their own -- a gate that exists and is not
* scheduled is the dormant shape seen from the other side.
*
* ⚠️ The pin deliberately needs NO workflow edit: `lint.yml` already invokes both
* legs, in the required `Lint & Repo Gates` job, on a trigger set that includes
* `merge_group` and with no `paths:` filter. It is the repo's busiest file and the
* assertion reads it rather than adding to it.
*/

import { readFileSync, writeFileSync } from 'node:fs';
Expand DownExpand Up@@ -1501,6 +1531,36 @@ function selfTest() {
refusalText
);

// ── WIRING: this gate, and its self-test, really run in CI ──────────────────
//
// ⭐ The half a clean tree cannot show, and the reason this block exists. Every
// other case above judges the RULES; this one judges whether anything runs them.
// `check-self-test-wired` is conditional in the wrong direction for that -- it
// requires "if CI runs the script, CI runs its --self-test too", so deleting BOTH
// lines from `lint.yml` leaves it green and silently retires the only instrument
// that catches a stale anchor. Measured: the census is what reddens when a cited
// file moves underneath a page nobody edited, so its scheduling is load-bearing,
// not incidental.
//
// Asserted against the workflow TEXT, following the precedent `check-doc-frontmatter`,
// `check-aggregator-roster` and `check-ci-filter-parity` set -- and, like the second
// docs root that gate added, this needed NO workflow edit: `lint.yml` already invokes
// both legs, and it is the repo's busiest file.
const SELF = 'scripts/check-system-context-census.mjs';
let lintYml = null;
try {
lintYml = readFileSync(join(ROOT, '.github/workflows/lint.yml'), 'utf8');
} catch (err) {
t(`WIRING: .github/workflows/lint.yml is readable`, false, err.code ?? err.message);
}
if (lintYml !== null) {
t(
'WIRING: lint.yml invokes this gate directly (the GATE INVOCATION IDIOM, not a package.json fence)',
lintYml.includes(`node ${SELF}\n`)
);
t('WIRING: lint.yml runs the --self-test leg too', lintYml.includes(`node ${SELF} --self-test`));
}

process.stdout.write(
failures === 0
? '\ncheck-system-context-census --self-test: all cases passed\n'
Expand Down
50 changes: 50 additions & 0 deletions scripts/regen-artifacts.mjs
Original file line numberDiff line numberDiff line change
Expand Up@@ -179,6 +179,45 @@ export const REGEN_ARTIFACTS = Object.freeze([
gen: 'gen:liveness-counts',
check: 'check:liveness',
},
// #13646. The elevation census page — a generated `file:line` anchor table, and
// the first row here owned by ROOT tooling rather than by `packages/spec` (the
// owner field #13585 added exists for exactly this).
//
// ⚠️ The row is the FILE, not `content/docs/permissions/**`, and the difference
// is safety rather than tidiness. Its routed sibling `content/docs/references/**`
// is a whole generated tree; `content/docs/permissions/` is 22 hand-written prose
// pages with ONE generated page among them, so the directory glob would hand 21
// prose files to a driver that resolves to OURS — laundering away a sibling's
// prose edit, which is the exact trade `migrations/registry.ts` is kept out of
// this table for. The glob is recorded in NOT_DRIVER_MANAGED below.
//
// Why it belongs here at all: two PRs that each ran `--fix` against their own
// tree write correct-for-themselves line numbers into the same rows, and the
// merged tree's correct values equal NEITHER side — measured on #13625's merge,
// where the five conflicted anchors resolved to `4408/5771/6019/6382/6575`
// against branch `4407/5770/…` and main `4284/5647/…`. A text merge cannot reach
// that answer from either input, so this is a deferral-and-regenerate shape.
//
// ⭐ And the deferral is safe in the direction that matters, which is the
// question `os-regen-merge.sh` raises about every path here — a driver that
// exits 0 trades a loud failure for a silent one unless something else still
// reddens. Here something does, on every PR: `check-system-context-census.mjs`
// runs in the required `Lint & Repo Gates` job with no `paths:` filter and on
// `merge_group`, it re-derives the census from the tree rather than reading the
// page back, and its scheduling is pinned by its own `--self-test` (#13646). The
// driver is therefore the cheap half here and never the only signal.
//
// No `readsDist`/`readsSchemaTree`: the census is an AST walk over `src/`, so a
// merged tree is the whole prerequisite. `gen` cannot launder a POPULATION change
// either — `--fix` re-anchors a pure shift and REFUSES when a site arrived or
// vanished, leaving the page untouched and the gate red (measured: exit 1, zero
// anchors rewritten, `[declared-count] ruling-sites says 109, the census says 110`).
{
path: 'content/docs/permissions/system-context.mdx',
gen: 'gen:system-context-census',
check: 'check:system-context-census',
owner: ROOT_OWNER,
},
]);

/**
Expand DownExpand Up@@ -238,6 +277,17 @@ export const NOT_DRIVER_MANAGED = Object.freeze([
+ 'registries and the other one is `scripts/adr-anchors.json` (#7301). Splitting this one too is '
+ 'a follow-up with its own measurement, not a rider.',
},
{
path: 'content/docs/permissions/**',
why:
'the DIRECTORY is not what #13646 routed, and recording that is the point of this ledger. '
+ '22 of its 23 pages are hand-written permissions prose; exactly one — `system-context.mdx`, '
+ 'declared above — is a generated anchor table. Routing the tree the way its sibling '
+ '`content/docs/references/**` is routed reads as symmetry and is not: that sibling is '
+ 'generated whole, this one would defer 21 prose files to OURS and lose the other side\'s '
+ 'edits silently. Route the generated FILE; leave the neighbours to text-merge, which is '
+ 'correct for prose and always was.',
},
{
path: 'docs/audits/**',
why:
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' fix(devx): route the elevation census page to os-regen, and pin the CI gate that is the real guard by claude[bot] · Pull Request #13732 · objectstack-ai/objectstack · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .gitattributes
Original file line numberDiff line numberDiff line change
Expand Up@@ -75,6 +75,23 @@
# hand-written measurement of how each type got where it is — and is NOT.
# Regenerating a Note would fabricate a verdict, which that README calls worse
# than a missing row.
#
# The elevation census page joined at #13646 — a generated `file:line` anchor
# table whose correct merged values are on NEITHER side of a conflict (measured on
# #13625: five conflicted anchors resolved to 4408/5771/6019/6382/6575 against
# branch 4407/5770/… and main 4284/5647/…), so no text merge and no hand merge can
# reach them. ⚠️ It is routed as the FILE and NOT as `content/docs/permissions/**`:
# unlike `content/docs/references/**` above, which is generated whole, that
# directory is 22 hand-written prose pages around one generated one, and the glob
# would defer the prose to OURS. See NOT_DRIVER_MANAGED for that entry.
#
# This is also the row where the header's own warning is answered rather than
# accepted: deferring is safe here because `scripts/check-system-context-census.mjs`
# still reddens on every PR from the required `Lint & Repo Gates` job — it
# RE-DERIVES the census from the tree, so it catches the stale anchors a merge
# leaves behind even when nothing conflicted, which is the majority case (#13625:
# 18 anchors stale, 5 marked). The driver removes hand-merge rounds; it is never
# the only signal.

packages/spec/spec-changes.json merge=os-regen
packages/spec/liveness/state-counts.md merge=os-regen
Expand All@@ -89,3 +106,4 @@ packages/spec/api-surface-signatures.json merge=os-regen
docs/protocol-upgrade-guide.md merge=os-regen
docs/audits/2026-07-unknown-key-strictness-ledger.counts.md merge=os-regen
content/docs/references/** merge=os-regen
content/docs/permissions/system-context.mdx merge=os-regen
4 changes: 3 additions & 1 deletion package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -146,7 +146,9 @@
"check:tenant-chokepoint": "node scripts/check-tenant-chokepoint.mjs --self-test && node scripts/check-tenant-chokepoint.mjs",
"check:stall-guard": "node scripts/run-with-stall-guard.mjs --self-test",
"check:stall-guard-budget": "node scripts/check-stall-guard-budget.mjs --self-test && node scripts/check-stall-guard-budget.mjs",
"check:stall-guard-headroom": "node scripts/measure-stall-guard-headroom.mjs --self-test"
"check:stall-guard-headroom": "node scripts/measure-stall-guard-headroom.mjs --self-test",
"gen:system-context-census": "node scripts/check-system-context-census.mjs --fix",
"check:system-context-census": "node scripts/check-system-context-census.mjs --self-test && node scripts/check-system-context-census.mjs"
},
"keywords": [
"objectstack",
Expand Down
60 changes: 60 additions & 0 deletions scripts/check-system-context-census.mjs
Original file line numberDiff line numberDiff line change
Expand Up@@ -119,6 +119,36 @@
* of zero files, a declared-count pattern that matches nothing, an UNENFORCED row
* that vanished or lost its date, and a ledger row that locates nothing are all
* exit 1 naming what could not be read.
*
* ## ⭐ Wiring, and why the self-test asserts it (#13646)
*
* This gate IS the "regenerate and diff" instrument for the page: it re-derives the
* census from the tree and reddens when the committed anchors disagree. That makes
* it the only thing standing between the page and the failure mode that has no
* other signal -- an anchor going stale because the file it CITES moved, in a merge
* that produced no conflict at all.
*
* Measured on `cc837dbfec` by shifting `plugin-sharing/src/sharing-service.ts` down
* 29 lines (main's real delta in the #13625 window) with the page untouched, which
* is the branch-never-touched-that-file case git merges clean and silent:
*
* gate on the shifted tree exit 1, 16 findings, naming every one of the five
* sharing-service anchors and the ledger row
* `--fix` then the gate 109 sites re-anchored, exit 0
*
* So the anchors are recoverable and the loss is loud -- PROVIDED the gate is
* scheduled. Nothing asserted that it was. `check-self-test-wired` is conditional
* in the wrong direction here: it requires that a script CI runs also has its
* `--self-test` run, so deleting BOTH invocations from `lint.yml` retires this gate
* with every check still green. The self-test therefore reads the workflow text and
* asserts both legs, the way `check-doc-frontmatter`, `check-aggregator-roster` and
* `check-ci-filter-parity` each assert their own -- a gate that exists and is not
* scheduled is the dormant shape seen from the other side.
*
* ⚠️ The pin deliberately needs NO workflow edit: `lint.yml` already invokes both
* legs, in the required `Lint & Repo Gates` job, on a trigger set that includes
* `merge_group` and with no `paths:` filter. It is the repo's busiest file and the
* assertion reads it rather than adding to it.
*/

import { readFileSync, writeFileSync } from 'node:fs';
Expand DownExpand Up@@ -1501,6 +1531,36 @@ function selfTest() {
refusalText
);

// ── WIRING: this gate, and its self-test, really run in CI ──────────────────
//
// ⭐ The half a clean tree cannot show, and the reason this block exists. Every
// other case above judges the RULES; this one judges whether anything runs them.
// `check-self-test-wired` is conditional in the wrong direction for that -- it
// requires "if CI runs the script, CI runs its --self-test too", so deleting BOTH
// lines from `lint.yml` leaves it green and silently retires the only instrument
// that catches a stale anchor. Measured: the census is what reddens when a cited
// file moves underneath a page nobody edited, so its scheduling is load-bearing,
// not incidental.
//
// Asserted against the workflow TEXT, following the precedent `check-doc-frontmatter`,
// `check-aggregator-roster` and `check-ci-filter-parity` set -- and, like the second
// docs root that gate added, this needed NO workflow edit: `lint.yml` already invokes
// both legs, and it is the repo's busiest file.
const SELF = 'scripts/check-system-context-census.mjs';
let lintYml = null;
try {
lintYml = readFileSync(join(ROOT, '.github/workflows/lint.yml'), 'utf8');
} catch (err) {
t(`WIRING: .github/workflows/lint.yml is readable`, false, err.code ?? err.message);
}
if (lintYml !== null) {
t(
'WIRING: lint.yml invokes this gate directly (the GATE INVOCATION IDIOM, not a package.json fence)',
lintYml.includes(`node ${SELF}\n`)
);
t('WIRING: lint.yml runs the --self-test leg too', lintYml.includes(`node ${SELF} --self-test`));
}

process.stdout.write(
failures === 0
? '\ncheck-system-context-census --self-test: all cases passed\n'
Expand Down
50 changes: 50 additions & 0 deletions scripts/regen-artifacts.mjs
Original file line numberDiff line numberDiff line change
Expand Up@@ -179,6 +179,45 @@ export const REGEN_ARTIFACTS = Object.freeze([
gen: 'gen:liveness-counts',
check: 'check:liveness',
},
// #13646. The elevation census page — a generated `file:line` anchor table, and
// the first row here owned by ROOT tooling rather than by `packages/spec` (the
// owner field #13585 added exists for exactly this).
//
// ⚠️ The row is the FILE, not `content/docs/permissions/**`, and the difference
// is safety rather than tidiness. Its routed sibling `content/docs/references/**`
// is a whole generated tree; `content/docs/permissions/` is 22 hand-written prose
// pages with ONE generated page among them, so the directory glob would hand 21
// prose files to a driver that resolves to OURS — laundering away a sibling's
// prose edit, which is the exact trade `migrations/registry.ts` is kept out of
// this table for. The glob is recorded in NOT_DRIVER_MANAGED below.
//
// Why it belongs here at all: two PRs that each ran `--fix` against their own
// tree write correct-for-themselves line numbers into the same rows, and the
// merged tree's correct values equal NEITHER side — measured on #13625's merge,
// where the five conflicted anchors resolved to `4408/5771/6019/6382/6575`
// against branch `4407/5770/…` and main `4284/5647/…`. A text merge cannot reach
// that answer from either input, so this is a deferral-and-regenerate shape.
//
// ⭐ And the deferral is safe in the direction that matters, which is the
// question `os-regen-merge.sh` raises about every path here — a driver that
// exits 0 trades a loud failure for a silent one unless something else still
// reddens. Here something does, on every PR: `check-system-context-census.mjs`
// runs in the required `Lint & Repo Gates` job with no `paths:` filter and on
// `merge_group`, it re-derives the census from the tree rather than reading the
// page back, and its scheduling is pinned by its own `--self-test` (#13646). The
// driver is therefore the cheap half here and never the only signal.
//
// No `readsDist`/`readsSchemaTree`: the census is an AST walk over `src/`, so a
// merged tree is the whole prerequisite. `gen` cannot launder a POPULATION change
// either — `--fix` re-anchors a pure shift and REFUSES when a site arrived or
// vanished, leaving the page untouched and the gate red (measured: exit 1, zero
// anchors rewritten, `[declared-count] ruling-sites says 109, the census says 110`).
{
path: 'content/docs/permissions/system-context.mdx',
gen: 'gen:system-context-census',
check: 'check:system-context-census',
owner: ROOT_OWNER,
},
]);

/**
Expand DownExpand Up@@ -238,6 +277,17 @@ export const NOT_DRIVER_MANAGED = Object.freeze([
+ 'registries and the other one is `scripts/adr-anchors.json` (#7301). Splitting this one too is '
+ 'a follow-up with its own measurement, not a rider.',
},
{
path: 'content/docs/permissions/**',
why:
'the DIRECTORY is not what #13646 routed, and recording that is the point of this ledger. '
+ '22 of its 23 pages are hand-written permissions prose; exactly one — `system-context.mdx`, '
+ 'declared above — is a generated anchor table. Routing the tree the way its sibling '
+ '`content/docs/references/**` is routed reads as symmetry and is not: that sibling is '
+ 'generated whole, this one would defer 21 prose files to OURS and lose the other side\'s '
+ 'edits silently. Route the generated FILE; leave the neighbours to text-merge, which is '
+ 'correct for prose and always was.',
},
{
path: 'docs/audits/**',
why:
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' fix(devx): route the elevation census page to os-regen, and pin the CI gate that is the real guard by claude[bot] · Pull Request #13732 · objectstack-ai/objectstack · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .gitattributes
Original file line numberDiff line numberDiff line change
Expand Up@@ -75,6 +75,23 @@
# hand-written measurement of how each type got where it is — and is NOT.
# Regenerating a Note would fabricate a verdict, which that README calls worse
# than a missing row.
#
# The elevation census page joined at #13646 — a generated `file:line` anchor
# table whose correct merged values are on NEITHER side of a conflict (measured on
# #13625: five conflicted anchors resolved to 4408/5771/6019/6382/6575 against
# branch 4407/5770/… and main 4284/5647/…), so no text merge and no hand merge can
# reach them. ⚠️ It is routed as the FILE and NOT as `content/docs/permissions/**`:
# unlike `content/docs/references/**` above, which is generated whole, that
# directory is 22 hand-written prose pages around one generated one, and the glob
# would defer the prose to OURS. See NOT_DRIVER_MANAGED for that entry.
#
# This is also the row where the header's own warning is answered rather than
# accepted: deferring is safe here because `scripts/check-system-context-census.mjs`
# still reddens on every PR from the required `Lint & Repo Gates` job — it
# RE-DERIVES the census from the tree, so it catches the stale anchors a merge
# leaves behind even when nothing conflicted, which is the majority case (#13625:
# 18 anchors stale, 5 marked). The driver removes hand-merge rounds; it is never
# the only signal.

packages/spec/spec-changes.json merge=os-regen
packages/spec/liveness/state-counts.md merge=os-regen
Expand All@@ -89,3 +106,4 @@ packages/spec/api-surface-signatures.json merge=os-regen
docs/protocol-upgrade-guide.md merge=os-regen
docs/audits/2026-07-unknown-key-strictness-ledger.counts.md merge=os-regen
content/docs/references/** merge=os-regen
content/docs/permissions/system-context.mdx merge=os-regen
4 changes: 3 additions & 1 deletion package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -146,7 +146,9 @@
"check:tenant-chokepoint": "node scripts/check-tenant-chokepoint.mjs --self-test && node scripts/check-tenant-chokepoint.mjs",
"check:stall-guard": "node scripts/run-with-stall-guard.mjs --self-test",
"check:stall-guard-budget": "node scripts/check-stall-guard-budget.mjs --self-test && node scripts/check-stall-guard-budget.mjs",
"check:stall-guard-headroom": "node scripts/measure-stall-guard-headroom.mjs --self-test"
"check:stall-guard-headroom": "node scripts/measure-stall-guard-headroom.mjs --self-test",
"gen:system-context-census": "node scripts/check-system-context-census.mjs --fix",
"check:system-context-census": "node scripts/check-system-context-census.mjs --self-test && node scripts/check-system-context-census.mjs"
},
"keywords": [
"objectstack",
Expand Down
60 changes: 60 additions & 0 deletions scripts/check-system-context-census.mjs
Original file line numberDiff line numberDiff line change
Expand Up@@ -119,6 +119,36 @@
* of zero files, a declared-count pattern that matches nothing, an UNENFORCED row
* that vanished or lost its date, and a ledger row that locates nothing are all
* exit 1 naming what could not be read.
*
* ## ⭐ Wiring, and why the self-test asserts it (#13646)
*
* This gate IS the "regenerate and diff" instrument for the page: it re-derives the
* census from the tree and reddens when the committed anchors disagree. That makes
* it the only thing standing between the page and the failure mode that has no
* other signal -- an anchor going stale because the file it CITES moved, in a merge
* that produced no conflict at all.
*
* Measured on `cc837dbfec` by shifting `plugin-sharing/src/sharing-service.ts` down
* 29 lines (main's real delta in the #13625 window) with the page untouched, which
* is the branch-never-touched-that-file case git merges clean and silent:
*
* gate on the shifted tree exit 1, 16 findings, naming every one of the five
* sharing-service anchors and the ledger row
* `--fix` then the gate 109 sites re-anchored, exit 0
*
* So the anchors are recoverable and the loss is loud -- PROVIDED the gate is
* scheduled. Nothing asserted that it was. `check-self-test-wired` is conditional
* in the wrong direction here: it requires that a script CI runs also has its
* `--self-test` run, so deleting BOTH invocations from `lint.yml` retires this gate
* with every check still green. The self-test therefore reads the workflow text and
* asserts both legs, the way `check-doc-frontmatter`, `check-aggregator-roster` and
* `check-ci-filter-parity` each assert their own -- a gate that exists and is not
* scheduled is the dormant shape seen from the other side.
*
* ⚠️ The pin deliberately needs NO workflow edit: `lint.yml` already invokes both
* legs, in the required `Lint & Repo Gates` job, on a trigger set that includes
* `merge_group` and with no `paths:` filter. It is the repo's busiest file and the
* assertion reads it rather than adding to it.
*/

import { readFileSync, writeFileSync } from 'node:fs';
Expand DownExpand Up@@ -1501,6 +1531,36 @@ function selfTest() {
refusalText
);

// ── WIRING: this gate, and its self-test, really run in CI ──────────────────
//
// ⭐ The half a clean tree cannot show, and the reason this block exists. Every
// other case above judges the RULES; this one judges whether anything runs them.
// `check-self-test-wired` is conditional in the wrong direction for that -- it
// requires "if CI runs the script, CI runs its --self-test too", so deleting BOTH
// lines from `lint.yml` leaves it green and silently retires the only instrument
// that catches a stale anchor. Measured: the census is what reddens when a cited
// file moves underneath a page nobody edited, so its scheduling is load-bearing,
// not incidental.
//
// Asserted against the workflow TEXT, following the precedent `check-doc-frontmatter`,
// `check-aggregator-roster` and `check-ci-filter-parity` set -- and, like the second
// docs root that gate added, this needed NO workflow edit: `lint.yml` already invokes
// both legs, and it is the repo's busiest file.
const SELF = 'scripts/check-system-context-census.mjs';
let lintYml = null;
try {
lintYml = readFileSync(join(ROOT, '.github/workflows/lint.yml'), 'utf8');
} catch (err) {
t(`WIRING: .github/workflows/lint.yml is readable`, false, err.code ?? err.message);
}
if (lintYml !== null) {
t(
'WIRING: lint.yml invokes this gate directly (the GATE INVOCATION IDIOM, not a package.json fence)',
lintYml.includes(`node ${SELF}\n`)
);
t('WIRING: lint.yml runs the --self-test leg too', lintYml.includes(`node ${SELF} --self-test`));
}

process.stdout.write(
failures === 0
? '\ncheck-system-context-census --self-test: all cases passed\n'
Expand Down
50 changes: 50 additions & 0 deletions scripts/regen-artifacts.mjs
Original file line numberDiff line numberDiff line change
Expand Up@@ -179,6 +179,45 @@ export const REGEN_ARTIFACTS = Object.freeze([
gen: 'gen:liveness-counts',
check: 'check:liveness',
},
// #13646. The elevation census page — a generated `file:line` anchor table, and
// the first row here owned by ROOT tooling rather than by `packages/spec` (the
// owner field #13585 added exists for exactly this).
//
// ⚠️ The row is the FILE, not `content/docs/permissions/**`, and the difference
// is safety rather than tidiness. Its routed sibling `content/docs/references/**`
// is a whole generated tree; `content/docs/permissions/` is 22 hand-written prose
// pages with ONE generated page among them, so the directory glob would hand 21
// prose files to a driver that resolves to OURS — laundering away a sibling's
// prose edit, which is the exact trade `migrations/registry.ts` is kept out of
// this table for. The glob is recorded in NOT_DRIVER_MANAGED below.
//
// Why it belongs here at all: two PRs that each ran `--fix` against their own
// tree write correct-for-themselves line numbers into the same rows, and the
// merged tree's correct values equal NEITHER side — measured on #13625's merge,
// where the five conflicted anchors resolved to `4408/5771/6019/6382/6575`
// against branch `4407/5770/…` and main `4284/5647/…`. A text merge cannot reach
// that answer from either input, so this is a deferral-and-regenerate shape.
//
// ⭐ And the deferral is safe in the direction that matters, which is the
// question `os-regen-merge.sh` raises about every path here — a driver that
// exits 0 trades a loud failure for a silent one unless something else still
// reddens. Here something does, on every PR: `check-system-context-census.mjs`
// runs in the required `Lint & Repo Gates` job with no `paths:` filter and on
// `merge_group`, it re-derives the census from the tree rather than reading the
// page back, and its scheduling is pinned by its own `--self-test` (#13646). The
// driver is therefore the cheap half here and never the only signal.
//
// No `readsDist`/`readsSchemaTree`: the census is an AST walk over `src/`, so a
// merged tree is the whole prerequisite. `gen` cannot launder a POPULATION change
// either — `--fix` re-anchors a pure shift and REFUSES when a site arrived or
// vanished, leaving the page untouched and the gate red (measured: exit 1, zero
// anchors rewritten, `[declared-count] ruling-sites says 109, the census says 110`).
{
path: 'content/docs/permissions/system-context.mdx',
gen: 'gen:system-context-census',
check: 'check:system-context-census',
owner: ROOT_OWNER,
},
]);

/**
Expand DownExpand Up@@ -238,6 +277,17 @@ export const NOT_DRIVER_MANAGED = Object.freeze([
+ 'registries and the other one is `scripts/adr-anchors.json` (#7301). Splitting this one too is '
+ 'a follow-up with its own measurement, not a rider.',
},
{
path: 'content/docs/permissions/**',
why:
'the DIRECTORY is not what #13646 routed, and recording that is the point of this ledger. '
+ '22 of its 23 pages are hand-written permissions prose; exactly one — `system-context.mdx`, '
+ 'declared above — is a generated anchor table. Routing the tree the way its sibling '
+ '`content/docs/references/**` is routed reads as symmetry and is not: that sibling is '
+ 'generated whole, this one would defer 21 prose files to OURS and lose the other side\'s '
+ 'edits silently. Route the generated FILE; leave the neighbours to text-merge, which is '
+ 'correct for prose and always was.',
},
{
path: 'docs/audits/**',
why:
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' fix(devx): route the elevation census page to os-regen, and pin the CI gate that is the real guard by claude[bot] · Pull Request #13732 · objectstack-ai/objectstack · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .gitattributes
Original file line numberDiff line numberDiff line change
Expand Up@@ -75,6 +75,23 @@
# hand-written measurement of how each type got where it is — and is NOT.
# Regenerating a Note would fabricate a verdict, which that README calls worse
# than a missing row.
#
# The elevation census page joined at #13646 — a generated `file:line` anchor
# table whose correct merged values are on NEITHER side of a conflict (measured on
# #13625: five conflicted anchors resolved to 4408/5771/6019/6382/6575 against
# branch 4407/5770/… and main 4284/5647/…), so no text merge and no hand merge can
# reach them. ⚠️ It is routed as the FILE and NOT as `content/docs/permissions/**`:
# unlike `content/docs/references/**` above, which is generated whole, that
# directory is 22 hand-written prose pages around one generated one, and the glob
# would defer the prose to OURS. See NOT_DRIVER_MANAGED for that entry.
#
# This is also the row where the header's own warning is answered rather than
# accepted: deferring is safe here because `scripts/check-system-context-census.mjs`
# still reddens on every PR from the required `Lint & Repo Gates` job — it
# RE-DERIVES the census from the tree, so it catches the stale anchors a merge
# leaves behind even when nothing conflicted, which is the majority case (#13625:
# 18 anchors stale, 5 marked). The driver removes hand-merge rounds; it is never
# the only signal.

packages/spec/spec-changes.json merge=os-regen
packages/spec/liveness/state-counts.md merge=os-regen
Expand All@@ -89,3 +106,4 @@ packages/spec/api-surface-signatures.json merge=os-regen
docs/protocol-upgrade-guide.md merge=os-regen
docs/audits/2026-07-unknown-key-strictness-ledger.counts.md merge=os-regen
content/docs/references/** merge=os-regen
content/docs/permissions/system-context.mdx merge=os-regen
4 changes: 3 additions & 1 deletion package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -146,7 +146,9 @@
"check:tenant-chokepoint": "node scripts/check-tenant-chokepoint.mjs --self-test && node scripts/check-tenant-chokepoint.mjs",
"check:stall-guard": "node scripts/run-with-stall-guard.mjs --self-test",
"check:stall-guard-budget": "node scripts/check-stall-guard-budget.mjs --self-test && node scripts/check-stall-guard-budget.mjs",
"check:stall-guard-headroom": "node scripts/measure-stall-guard-headroom.mjs --self-test"
"check:stall-guard-headroom": "node scripts/measure-stall-guard-headroom.mjs --self-test",
"gen:system-context-census": "node scripts/check-system-context-census.mjs --fix",
"check:system-context-census": "node scripts/check-system-context-census.mjs --self-test && node scripts/check-system-context-census.mjs"
},
"keywords": [
"objectstack",
Expand Down
60 changes: 60 additions & 0 deletions scripts/check-system-context-census.mjs
Original file line numberDiff line numberDiff line change
Expand Up@@ -119,6 +119,36 @@
* of zero files, a declared-count pattern that matches nothing, an UNENFORCED row
* that vanished or lost its date, and a ledger row that locates nothing are all
* exit 1 naming what could not be read.
*
* ## ⭐ Wiring, and why the self-test asserts it (#13646)
*
* This gate IS the "regenerate and diff" instrument for the page: it re-derives the
* census from the tree and reddens when the committed anchors disagree. That makes
* it the only thing standing between the page and the failure mode that has no
* other signal -- an anchor going stale because the file it CITES moved, in a merge
* that produced no conflict at all.
*
* Measured on `cc837dbfec` by shifting `plugin-sharing/src/sharing-service.ts` down
* 29 lines (main's real delta in the #13625 window) with the page untouched, which
* is the branch-never-touched-that-file case git merges clean and silent:
*
* gate on the shifted tree exit 1, 16 findings, naming every one of the five
* sharing-service anchors and the ledger row
* `--fix` then the gate 109 sites re-anchored, exit 0
*
* So the anchors are recoverable and the loss is loud -- PROVIDED the gate is
* scheduled. Nothing asserted that it was. `check-self-test-wired` is conditional
* in the wrong direction here: it requires that a script CI runs also has its
* `--self-test` run, so deleting BOTH invocations from `lint.yml` retires this gate
* with every check still green. The self-test therefore reads the workflow text and
* asserts both legs, the way `check-doc-frontmatter`, `check-aggregator-roster` and
* `check-ci-filter-parity` each assert their own -- a gate that exists and is not
* scheduled is the dormant shape seen from the other side.
*
* ⚠️ The pin deliberately needs NO workflow edit: `lint.yml` already invokes both
* legs, in the required `Lint & Repo Gates` job, on a trigger set that includes
* `merge_group` and with no `paths:` filter. It is the repo's busiest file and the
* assertion reads it rather than adding to it.
*/

import { readFileSync, writeFileSync } from 'node:fs';
Expand DownExpand Up@@ -1501,6 +1531,36 @@ function selfTest() {
refusalText
);

// ── WIRING: this gate, and its self-test, really run in CI ──────────────────
//
// ⭐ The half a clean tree cannot show, and the reason this block exists. Every
// other case above judges the RULES; this one judges whether anything runs them.
// `check-self-test-wired` is conditional in the wrong direction for that -- it
// requires "if CI runs the script, CI runs its --self-test too", so deleting BOTH
// lines from `lint.yml` leaves it green and silently retires the only instrument
// that catches a stale anchor. Measured: the census is what reddens when a cited
// file moves underneath a page nobody edited, so its scheduling is load-bearing,
// not incidental.
//
// Asserted against the workflow TEXT, following the precedent `check-doc-frontmatter`,
// `check-aggregator-roster` and `check-ci-filter-parity` set -- and, like the second
// docs root that gate added, this needed NO workflow edit: `lint.yml` already invokes
// both legs, and it is the repo's busiest file.
const SELF = 'scripts/check-system-context-census.mjs';
let lintYml = null;
try {
lintYml = readFileSync(join(ROOT, '.github/workflows/lint.yml'), 'utf8');
} catch (err) {
t(`WIRING: .github/workflows/lint.yml is readable`, false, err.code ?? err.message);
}
if (lintYml !== null) {
t(
'WIRING: lint.yml invokes this gate directly (the GATE INVOCATION IDIOM, not a package.json fence)',
lintYml.includes(`node ${SELF}\n`)
);
t('WIRING: lint.yml runs the --self-test leg too', lintYml.includes(`node ${SELF} --self-test`));
}

process.stdout.write(
failures === 0
? '\ncheck-system-context-census --self-test: all cases passed\n'
Expand Down
50 changes: 50 additions & 0 deletions scripts/regen-artifacts.mjs
Original file line numberDiff line numberDiff line change
Expand Up@@ -179,6 +179,45 @@ export const REGEN_ARTIFACTS = Object.freeze([
gen: 'gen:liveness-counts',
check: 'check:liveness',
},
// #13646. The elevation census page — a generated `file:line` anchor table, and
// the first row here owned by ROOT tooling rather than by `packages/spec` (the
// owner field #13585 added exists for exactly this).
//
// ⚠️ The row is the FILE, not `content/docs/permissions/**`, and the difference
// is safety rather than tidiness. Its routed sibling `content/docs/references/**`
// is a whole generated tree; `content/docs/permissions/` is 22 hand-written prose
// pages with ONE generated page among them, so the directory glob would hand 21
// prose files to a driver that resolves to OURS — laundering away a sibling's
// prose edit, which is the exact trade `migrations/registry.ts` is kept out of
// this table for. The glob is recorded in NOT_DRIVER_MANAGED below.
//
// Why it belongs here at all: two PRs that each ran `--fix` against their own
// tree write correct-for-themselves line numbers into the same rows, and the
// merged tree's correct values equal NEITHER side — measured on #13625's merge,
// where the five conflicted anchors resolved to `4408/5771/6019/6382/6575`
// against branch `4407/5770/…` and main `4284/5647/…`. A text merge cannot reach
// that answer from either input, so this is a deferral-and-regenerate shape.
//
// ⭐ And the deferral is safe in the direction that matters, which is the
// question `os-regen-merge.sh` raises about every path here — a driver that
// exits 0 trades a loud failure for a silent one unless something else still
// reddens. Here something does, on every PR: `check-system-context-census.mjs`
// runs in the required `Lint & Repo Gates` job with no `paths:` filter and on
// `merge_group`, it re-derives the census from the tree rather than reading the
// page back, and its scheduling is pinned by its own `--self-test` (#13646). The
// driver is therefore the cheap half here and never the only signal.
//
// No `readsDist`/`readsSchemaTree`: the census is an AST walk over `src/`, so a
// merged tree is the whole prerequisite. `gen` cannot launder a POPULATION change
// either — `--fix` re-anchors a pure shift and REFUSES when a site arrived or
// vanished, leaving the page untouched and the gate red (measured: exit 1, zero
// anchors rewritten, `[declared-count] ruling-sites says 109, the census says 110`).
{
path: 'content/docs/permissions/system-context.mdx',
gen: 'gen:system-context-census',
check: 'check:system-context-census',
owner: ROOT_OWNER,
},
]);

/**
Expand DownExpand Up@@ -238,6 +277,17 @@ export const NOT_DRIVER_MANAGED = Object.freeze([
+ 'registries and the other one is `scripts/adr-anchors.json` (#7301). Splitting this one too is '
+ 'a follow-up with its own measurement, not a rider.',
},
{
path: 'content/docs/permissions/**',
why:
'the DIRECTORY is not what #13646 routed, and recording that is the point of this ledger. '
+ '22 of its 23 pages are hand-written permissions prose; exactly one — `system-context.mdx`, '
+ 'declared above — is a generated anchor table. Routing the tree the way its sibling '
+ '`content/docs/references/**` is routed reads as symmetry and is not: that sibling is '
+ 'generated whole, this one would defer 21 prose files to OURS and lose the other side\'s '
+ 'edits silently. Route the generated FILE; leave the neighbours to text-merge, which is '
+ 'correct for prose and always was.',
},
{
path: 'docs/audits/**',
why:
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' fix(devx): route the elevation census page to os-regen, and pin the CI gate that is the real guard by claude[bot] · Pull Request #13732 · objectstack-ai/objectstack · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .gitattributes
Original file line numberDiff line numberDiff line change
Expand Up@@ -75,6 +75,23 @@
# hand-written measurement of how each type got where it is — and is NOT.
# Regenerating a Note would fabricate a verdict, which that README calls worse
# than a missing row.
#
# The elevation census page joined at #13646 — a generated `file:line` anchor
# table whose correct merged values are on NEITHER side of a conflict (measured on
# #13625: five conflicted anchors resolved to 4408/5771/6019/6382/6575 against
# branch 4407/5770/… and main 4284/5647/…), so no text merge and no hand merge can
# reach them. ⚠️ It is routed as the FILE and NOT as `content/docs/permissions/**`:
# unlike `content/docs/references/**` above, which is generated whole, that
# directory is 22 hand-written prose pages around one generated one, and the glob
# would defer the prose to OURS. See NOT_DRIVER_MANAGED for that entry.
#
# This is also the row where the header's own warning is answered rather than
# accepted: deferring is safe here because `scripts/check-system-context-census.mjs`
# still reddens on every PR from the required `Lint & Repo Gates` job — it
# RE-DERIVES the census from the tree, so it catches the stale anchors a merge
# leaves behind even when nothing conflicted, which is the majority case (#13625:
# 18 anchors stale, 5 marked). The driver removes hand-merge rounds; it is never
# the only signal.

packages/spec/spec-changes.json merge=os-regen
packages/spec/liveness/state-counts.md merge=os-regen
Expand All@@ -89,3 +106,4 @@ packages/spec/api-surface-signatures.json merge=os-regen
docs/protocol-upgrade-guide.md merge=os-regen
docs/audits/2026-07-unknown-key-strictness-ledger.counts.md merge=os-regen
content/docs/references/** merge=os-regen
content/docs/permissions/system-context.mdx merge=os-regen
4 changes: 3 additions & 1 deletion package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -146,7 +146,9 @@
"check:tenant-chokepoint": "node scripts/check-tenant-chokepoint.mjs --self-test && node scripts/check-tenant-chokepoint.mjs",
"check:stall-guard": "node scripts/run-with-stall-guard.mjs --self-test",
"check:stall-guard-budget": "node scripts/check-stall-guard-budget.mjs --self-test && node scripts/check-stall-guard-budget.mjs",
"check:stall-guard-headroom": "node scripts/measure-stall-guard-headroom.mjs --self-test"
"check:stall-guard-headroom": "node scripts/measure-stall-guard-headroom.mjs --self-test",
"gen:system-context-census": "node scripts/check-system-context-census.mjs --fix",
"check:system-context-census": "node scripts/check-system-context-census.mjs --self-test && node scripts/check-system-context-census.mjs"
},
"keywords": [
"objectstack",
Expand Down
60 changes: 60 additions & 0 deletions scripts/check-system-context-census.mjs
Original file line numberDiff line numberDiff line change
Expand Up@@ -119,6 +119,36 @@
* of zero files, a declared-count pattern that matches nothing, an UNENFORCED row
* that vanished or lost its date, and a ledger row that locates nothing are all
* exit 1 naming what could not be read.
*
* ## ⭐ Wiring, and why the self-test asserts it (#13646)
*
* This gate IS the "regenerate and diff" instrument for the page: it re-derives the
* census from the tree and reddens when the committed anchors disagree. That makes
* it the only thing standing between the page and the failure mode that has no
* other signal -- an anchor going stale because the file it CITES moved, in a merge
* that produced no conflict at all.
*
* Measured on `cc837dbfec` by shifting `plugin-sharing/src/sharing-service.ts` down
* 29 lines (main's real delta in the #13625 window) with the page untouched, which
* is the branch-never-touched-that-file case git merges clean and silent:
*
* gate on the shifted tree exit 1, 16 findings, naming every one of the five
* sharing-service anchors and the ledger row
* `--fix` then the gate 109 sites re-anchored, exit 0
*
* So the anchors are recoverable and the loss is loud -- PROVIDED the gate is
* scheduled. Nothing asserted that it was. `check-self-test-wired` is conditional
* in the wrong direction here: it requires that a script CI runs also has its
* `--self-test` run, so deleting BOTH invocations from `lint.yml` retires this gate
* with every check still green. The self-test therefore reads the workflow text and
* asserts both legs, the way `check-doc-frontmatter`, `check-aggregator-roster` and
* `check-ci-filter-parity` each assert their own -- a gate that exists and is not
* scheduled is the dormant shape seen from the other side.
*
* ⚠️ The pin deliberately needs NO workflow edit: `lint.yml` already invokes both
* legs, in the required `Lint & Repo Gates` job, on a trigger set that includes
* `merge_group` and with no `paths:` filter. It is the repo's busiest file and the
* assertion reads it rather than adding to it.
*/

import { readFileSync, writeFileSync } from 'node:fs';
Expand DownExpand Up@@ -1501,6 +1531,36 @@ function selfTest() {
refusalText
);

// ── WIRING: this gate, and its self-test, really run in CI ──────────────────
//
// ⭐ The half a clean tree cannot show, and the reason this block exists. Every
// other case above judges the RULES; this one judges whether anything runs them.
// `check-self-test-wired` is conditional in the wrong direction for that -- it
// requires "if CI runs the script, CI runs its --self-test too", so deleting BOTH
// lines from `lint.yml` leaves it green and silently retires the only instrument
// that catches a stale anchor. Measured: the census is what reddens when a cited
// file moves underneath a page nobody edited, so its scheduling is load-bearing,
// not incidental.
//
// Asserted against the workflow TEXT, following the precedent `check-doc-frontmatter`,
// `check-aggregator-roster` and `check-ci-filter-parity` set -- and, like the second
// docs root that gate added, this needed NO workflow edit: `lint.yml` already invokes
// both legs, and it is the repo's busiest file.
const SELF = 'scripts/check-system-context-census.mjs';
let lintYml = null;
try {
lintYml = readFileSync(join(ROOT, '.github/workflows/lint.yml'), 'utf8');
} catch (err) {
t(`WIRING: .github/workflows/lint.yml is readable`, false, err.code ?? err.message);
}
if (lintYml !== null) {
t(
'WIRING: lint.yml invokes this gate directly (the GATE INVOCATION IDIOM, not a package.json fence)',
lintYml.includes(`node ${SELF}\n`)
);
t('WIRING: lint.yml runs the --self-test leg too', lintYml.includes(`node ${SELF} --self-test`));
}

process.stdout.write(
failures === 0
? '\ncheck-system-context-census --self-test: all cases passed\n'
Expand Down
50 changes: 50 additions & 0 deletions scripts/regen-artifacts.mjs
Original file line numberDiff line numberDiff line change
Expand Up@@ -179,6 +179,45 @@ export const REGEN_ARTIFACTS = Object.freeze([
gen: 'gen:liveness-counts',
check: 'check:liveness',
},
// #13646. The elevation census page — a generated `file:line` anchor table, and
// the first row here owned by ROOT tooling rather than by `packages/spec` (the
// owner field #13585 added exists for exactly this).
//
// ⚠️ The row is the FILE, not `content/docs/permissions/**`, and the difference
// is safety rather than tidiness. Its routed sibling `content/docs/references/**`
// is a whole generated tree; `content/docs/permissions/` is 22 hand-written prose
// pages with ONE generated page among them, so the directory glob would hand 21
// prose files to a driver that resolves to OURS — laundering away a sibling's
// prose edit, which is the exact trade `migrations/registry.ts` is kept out of
// this table for. The glob is recorded in NOT_DRIVER_MANAGED below.
//
// Why it belongs here at all: two PRs that each ran `--fix` against their own
// tree write correct-for-themselves line numbers into the same rows, and the
// merged tree's correct values equal NEITHER side — measured on #13625's merge,
// where the five conflicted anchors resolved to `4408/5771/6019/6382/6575`
// against branch `4407/5770/…` and main `4284/5647/…`. A text merge cannot reach
// that answer from either input, so this is a deferral-and-regenerate shape.
//
// ⭐ And the deferral is safe in the direction that matters, which is the
// question `os-regen-merge.sh` raises about every path here — a driver that
// exits 0 trades a loud failure for a silent one unless something else still
// reddens. Here something does, on every PR: `check-system-context-census.mjs`
// runs in the required `Lint & Repo Gates` job with no `paths:` filter and on
// `merge_group`, it re-derives the census from the tree rather than reading the
// page back, and its scheduling is pinned by its own `--self-test` (#13646). The
// driver is therefore the cheap half here and never the only signal.
//
// No `readsDist`/`readsSchemaTree`: the census is an AST walk over `src/`, so a
// merged tree is the whole prerequisite. `gen` cannot launder a POPULATION change
// either — `--fix` re-anchors a pure shift and REFUSES when a site arrived or
// vanished, leaving the page untouched and the gate red (measured: exit 1, zero
// anchors rewritten, `[declared-count] ruling-sites says 109, the census says 110`).
{
path: 'content/docs/permissions/system-context.mdx',
gen: 'gen:system-context-census',
check: 'check:system-context-census',
owner: ROOT_OWNER,
},
]);

/**
Expand DownExpand Up@@ -238,6 +277,17 @@ export const NOT_DRIVER_MANAGED = Object.freeze([
+ 'registries and the other one is `scripts/adr-anchors.json` (#7301). Splitting this one too is '
+ 'a follow-up with its own measurement, not a rider.',
},
{
path: 'content/docs/permissions/**',
why:
'the DIRECTORY is not what #13646 routed, and recording that is the point of this ledger. '
+ '22 of its 23 pages are hand-written permissions prose; exactly one — `system-context.mdx`, '
+ 'declared above — is a generated anchor table. Routing the tree the way its sibling '
+ '`content/docs/references/**` is routed reads as symmetry and is not: that sibling is '
+ 'generated whole, this one would defer 21 prose files to OURS and lose the other side\'s '
+ 'edits silently. Route the generated FILE; leave the neighbours to text-merge, which is '
+ 'correct for prose and always was.',
},
{
path: 'docs/audits/**',
why:
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); fix(devx): route the elevation census page to os-regen, and pin the CI gate that is the real guard by claude[bot] · Pull Request #13732 · objectstack-ai/objectstack · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .gitattributes
Original file line numberDiff line numberDiff line change
Expand Up@@ -75,6 +75,23 @@
# hand-written measurement of how each type got where it is — and is NOT.
# Regenerating a Note would fabricate a verdict, which that README calls worse
# than a missing row.
#
# The elevation census page joined at #13646 — a generated `file:line` anchor
# table whose correct merged values are on NEITHER side of a conflict (measured on
# #13625: five conflicted anchors resolved to 4408/5771/6019/6382/6575 against
# branch 4407/5770/… and main 4284/5647/…), so no text merge and no hand merge can
# reach them. ⚠️ It is routed as the FILE and NOT as `content/docs/permissions/**`:
# unlike `content/docs/references/**` above, which is generated whole, that
# directory is 22 hand-written prose pages around one generated one, and the glob
# would defer the prose to OURS. See NOT_DRIVER_MANAGED for that entry.
#
# This is also the row where the header's own warning is answered rather than
# accepted: deferring is safe here because `scripts/check-system-context-census.mjs`
# still reddens on every PR from the required `Lint & Repo Gates` job — it
# RE-DERIVES the census from the tree, so it catches the stale anchors a merge
# leaves behind even when nothing conflicted, which is the majority case (#13625:
# 18 anchors stale, 5 marked). The driver removes hand-merge rounds; it is never
# the only signal.

packages/spec/spec-changes.json merge=os-regen
packages/spec/liveness/state-counts.md merge=os-regen
Expand All@@ -89,3 +106,4 @@ packages/spec/api-surface-signatures.json merge=os-regen
docs/protocol-upgrade-guide.md merge=os-regen
docs/audits/2026-07-unknown-key-strictness-ledger.counts.md merge=os-regen
content/docs/references/** merge=os-regen
content/docs/permissions/system-context.mdx merge=os-regen
4 changes: 3 additions & 1 deletion package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -146,7 +146,9 @@
"check:tenant-chokepoint": "node scripts/check-tenant-chokepoint.mjs --self-test && node scripts/check-tenant-chokepoint.mjs",
"check:stall-guard": "node scripts/run-with-stall-guard.mjs --self-test",
"check:stall-guard-budget": "node scripts/check-stall-guard-budget.mjs --self-test && node scripts/check-stall-guard-budget.mjs",
"check:stall-guard-headroom": "node scripts/measure-stall-guard-headroom.mjs --self-test"
"check:stall-guard-headroom": "node scripts/measure-stall-guard-headroom.mjs --self-test",
"gen:system-context-census": "node scripts/check-system-context-census.mjs --fix",
"check:system-context-census": "node scripts/check-system-context-census.mjs --self-test && node scripts/check-system-context-census.mjs"
},
"keywords": [
"objectstack",
Expand Down
60 changes: 60 additions & 0 deletions scripts/check-system-context-census.mjs
Original file line numberDiff line numberDiff line change
Expand Up@@ -119,6 +119,36 @@
* of zero files, a declared-count pattern that matches nothing, an UNENFORCED row
* that vanished or lost its date, and a ledger row that locates nothing are all
* exit 1 naming what could not be read.
*
* ## ⭐ Wiring, and why the self-test asserts it (#13646)
*
* This gate IS the "regenerate and diff" instrument for the page: it re-derives the
* census from the tree and reddens when the committed anchors disagree. That makes
* it the only thing standing between the page and the failure mode that has no
* other signal -- an anchor going stale because the file it CITES moved, in a merge
* that produced no conflict at all.
*
* Measured on `cc837dbfec` by shifting `plugin-sharing/src/sharing-service.ts` down
* 29 lines (main's real delta in the #13625 window) with the page untouched, which
* is the branch-never-touched-that-file case git merges clean and silent:
*
* gate on the shifted tree exit 1, 16 findings, naming every one of the five
* sharing-service anchors and the ledger row
* `--fix` then the gate 109 sites re-anchored, exit 0
*
* So the anchors are recoverable and the loss is loud -- PROVIDED the gate is
* scheduled. Nothing asserted that it was. `check-self-test-wired` is conditional
* in the wrong direction here: it requires that a script CI runs also has its
* `--self-test` run, so deleting BOTH invocations from `lint.yml` retires this gate
* with every check still green. The self-test therefore reads the workflow text and
* asserts both legs, the way `check-doc-frontmatter`, `check-aggregator-roster` and
* `check-ci-filter-parity` each assert their own -- a gate that exists and is not
* scheduled is the dormant shape seen from the other side.
*
* ⚠️ The pin deliberately needs NO workflow edit: `lint.yml` already invokes both
* legs, in the required `Lint & Repo Gates` job, on a trigger set that includes
* `merge_group` and with no `paths:` filter. It is the repo's busiest file and the
* assertion reads it rather than adding to it.
*/

import { readFileSync, writeFileSync } from 'node:fs';
Expand DownExpand Up@@ -1501,6 +1531,36 @@ function selfTest() {
refusalText
);

// ── WIRING: this gate, and its self-test, really run in CI ──────────────────
//
// ⭐ The half a clean tree cannot show, and the reason this block exists. Every
// other case above judges the RULES; this one judges whether anything runs them.
// `check-self-test-wired` is conditional in the wrong direction for that -- it
// requires "if CI runs the script, CI runs its --self-test too", so deleting BOTH
// lines from `lint.yml` leaves it green and silently retires the only instrument
// that catches a stale anchor. Measured: the census is what reddens when a cited
// file moves underneath a page nobody edited, so its scheduling is load-bearing,
// not incidental.
//
// Asserted against the workflow TEXT, following the precedent `check-doc-frontmatter`,
// `check-aggregator-roster` and `check-ci-filter-parity` set -- and, like the second
// docs root that gate added, this needed NO workflow edit: `lint.yml` already invokes
// both legs, and it is the repo's busiest file.
const SELF = 'scripts/check-system-context-census.mjs';
let lintYml = null;
try {
lintYml = readFileSync(join(ROOT, '.github/workflows/lint.yml'), 'utf8');
} catch (err) {
t(`WIRING: .github/workflows/lint.yml is readable`, false, err.code ?? err.message);
}
if (lintYml !== null) {
t(
'WIRING: lint.yml invokes this gate directly (the GATE INVOCATION IDIOM, not a package.json fence)',
lintYml.includes(`node ${SELF}\n`)
);
t('WIRING: lint.yml runs the --self-test leg too', lintYml.includes(`node ${SELF} --self-test`));
}

process.stdout.write(
failures === 0
? '\ncheck-system-context-census --self-test: all cases passed\n'
Expand Down
50 changes: 50 additions & 0 deletions scripts/regen-artifacts.mjs
Original file line numberDiff line numberDiff line change
Expand Up@@ -179,6 +179,45 @@ export const REGEN_ARTIFACTS = Object.freeze([
gen: 'gen:liveness-counts',
check: 'check:liveness',
},
// #13646. The elevation census page — a generated `file:line` anchor table, and
// the first row here owned by ROOT tooling rather than by `packages/spec` (the
// owner field #13585 added exists for exactly this).
//
// ⚠️ The row is the FILE, not `content/docs/permissions/**`, and the difference
// is safety rather than tidiness. Its routed sibling `content/docs/references/**`
// is a whole generated tree; `content/docs/permissions/` is 22 hand-written prose
// pages with ONE generated page among them, so the directory glob would hand 21
// prose files to a driver that resolves to OURS — laundering away a sibling's
// prose edit, which is the exact trade `migrations/registry.ts` is kept out of
// this table for. The glob is recorded in NOT_DRIVER_MANAGED below.
//
// Why it belongs here at all: two PRs that each ran `--fix` against their own
// tree write correct-for-themselves line numbers into the same rows, and the
// merged tree's correct values equal NEITHER side — measured on #13625's merge,
// where the five conflicted anchors resolved to `4408/5771/6019/6382/6575`
// against branch `4407/5770/…` and main `4284/5647/…`. A text merge cannot reach
// that answer from either input, so this is a deferral-and-regenerate shape.
//
// ⭐ And the deferral is safe in the direction that matters, which is the
// question `os-regen-merge.sh` raises about every path here — a driver that
// exits 0 trades a loud failure for a silent one unless something else still
// reddens. Here something does, on every PR: `check-system-context-census.mjs`
// runs in the required `Lint & Repo Gates` job with no `paths:` filter and on
// `merge_group`, it re-derives the census from the tree rather than reading the
// page back, and its scheduling is pinned by its own `--self-test` (#13646). The
// driver is therefore the cheap half here and never the only signal.
//
// No `readsDist`/`readsSchemaTree`: the census is an AST walk over `src/`, so a
// merged tree is the whole prerequisite. `gen` cannot launder a POPULATION change
// either — `--fix` re-anchors a pure shift and REFUSES when a site arrived or
// vanished, leaving the page untouched and the gate red (measured: exit 1, zero
// anchors rewritten, `[declared-count] ruling-sites says 109, the census says 110`).
{
path: 'content/docs/permissions/system-context.mdx',
gen: 'gen:system-context-census',
check: 'check:system-context-census',
owner: ROOT_OWNER,
},
]);

/**
Expand DownExpand Up@@ -238,6 +277,17 @@ export const NOT_DRIVER_MANAGED = Object.freeze([
+ 'registries and the other one is `scripts/adr-anchors.json` (#7301). Splitting this one too is '
+ 'a follow-up with its own measurement, not a rider.',
},
{
path: 'content/docs/permissions/**',
why:
'the DIRECTORY is not what #13646 routed, and recording that is the point of this ledger. '
+ '22 of its 23 pages are hand-written permissions prose; exactly one — `system-context.mdx`, '
+ 'declared above — is a generated anchor table. Routing the tree the way its sibling '
+ '`content/docs/references/**` is routed reads as symmetry and is not: that sibling is '
+ 'generated whole, this one would defer 21 prose files to OURS and lose the other side\'s '
+ 'edits silently. Route the generated FILE; leave the neighbours to text-merge, which is '
+ 'correct for prose and always was.',
},
{
path: 'docs/audits/**',
why:
Expand Down
Loading