') + ')', '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('^' + ".*" + ', '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" + ', '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('^' + ".*" + ', '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
You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Both halves ship. But the load-bearing half turned out to already exist, and the
measurement that shows it also changes what the merge-driver half is allowed to be.
Verified on d32b0f501. Diff is 4 files, +131/−1, and zero lines of .github/workflows/lint.yml — see "No workflow edit" below.
⭐ Zone 2 falsified — and so is Zone 1's premise for half 1
Triage ruled that the load-bearing half is "一道「重生成并 diff」的 CI 检查", on the
grounds that it is the only instrument reaching the 13 anchors that went stale with no
conflict marker. That instrument is already in the tree, already required, and already
fires on exactly that case.
scripts/check-system-context-census.mjs re-derives the census from the tree with an AST
walk and compares it to the committed page — its POPULATION check requires every read site
the census finds to be anchored at its exact file:line. It runs in .github/workflows/lint.yml as the job lint, whose name: is the required status
context Lint & Repo Gates (node scripts/check-required-contexts.mjs), on pull_request + merge_group + push:main, with no paths: filter.
Reproducing the card's own silent case on cc837dbfec — shift plugin-sharing/src/sharing-service.ts down 29 lines (main's real delta in the #13625
window) and leave the page untouched, which is precisely the
branch-never-touched-that-file shape git merges clean:
gate on the shifted tree exit 1, 16 findings
[site-without-a-row] sharing-service.ts:683 / :949 / :1036 / :1237 / :1315 / :1367 / :1626
[anchor-is-not-a-read-site] the page still anchors :654 / :920 / :1007 / :1338 / :1597
[ledger-row-unused] NON_READ_ANCHORS row 34
`--fix` then the gate 109 sites re-anchored, exit 0
Those are the card's own +29 values (625→654, 891→920, 978→1007, 1568→1597, 1309→1338) — the gate names every one of them. ⇒ The silent 13 are not silent to CI.
What was actually missing: nothing asserted the gate is scheduled
check-self-test-wired is conditional in the wrong direction for this — it requires that
a script CI runs also has its --self-test run. Delete both invocations from lint.yml and it goes green, silently retiring the only instrument that catches a stale
anchor. Ablated, with the mutation confirmed on disk (2 invocations → 0):
--self-test on the ablated tree exit 1 — both WIRING cases FAIL
production run, same tree exit 0 — GREEN
The production run cannot see its own descheduling, which is exactly why the assertion
belongs in --self-test. Added there, following the precedent check-doc-frontmatter, check-aggregator-roster and check-ci-filter-parity set. Self-test now 37 cases, green.
No workflow edit — deliberately
lint.yml already invokes both legs, so the pin reads the workflow instead of adding
to it. That is the same move check-doc-frontmatter records for its second docs root
("lint.yml is the repo's busiest file and a second step would have been a third
concurrent edit of it"). ⇒ This PR does not touch lint.yml at all, so it does not
contend with #13584 and does not consume the slot #13582 is held for.
Half 2 — the merge driver route, scoped to the FILE
Registered in scripts/regen-artifacts.mjs (the single source of truth) plus .gitattributes, with gen:/check: in the root manifest. This is the first
production row owned by ROOT tooling — it exercises the owner field #13585 added,
which until now only synthetic self-test cases touched:
✓ .gitattributes ↔ regen-artifacts.mjs agree on 14 path(s)
✓ all 28 gen:/check: names resolve in their declared owner
(@objectstack/spec (packages/spec/package.json), @objectstack/spec-monorepo (package.json))
⚠️A2.3 is falsified as written. The card and the dispatch both proposed routing content/docs/permissions/**. That glob is not safe: unlike the routed sibling content/docs/references/**, which is generated whole, content/docs/permissions/ is 22 hand-written prose pages around exactly one generated page. The directory route
would defer 21 prose files to OURS and drop the other side's edits silently — the exact
trade packages/spec/src/migrations/registry.ts is kept out of the table for. Routed as
the file; the glob is recorded in NOT_DRIVER_MANAGED so the next author meets the
reasoning instead of the omission.
The header's own warning, answered rather than accepted
os-regen-merge.sh warns that a routed path can "merge with exit 0 and zero conflict
markers while SILENTLY DROPPING one side's changes". Here something still reddens: the
census gate above, on every PR, from a required job, re-deriving from the tree rather than
reading the page back. The driver removes hand-merge rounds; it is never the only signal.
⇒ Triage's ordering constraint ("第 1 项未落地前 ⛔ 不得合入第 2 项") is satisfied — the
CI instrument is in place before the routing, because it was already there.
Nor can the gen leg launder a population change. Injecting a new elevation read site
and running --fix:
exit 1, 0 anchors rewritten, page left byte-identical
::error::[declared-count] `ruling-sites` says 109, the census says 110
--fix re-anchors a pure shift and REFUSES when a site arrived or vanished, so the
pre-commit gate — which spawns check, never gen — stays red until a human writes the row.
none — zero new Date() / toISOString in the script
⇒ A2.1 holds (3s is not "minutes"; it was already affordable enough to be running). A2.2
holds — the output is a pure function of the tree, so the check cannot red on itself.
Scope question the card raised: which other generated artifacts are outside the routing?
Measured across all 79 manifests: 21 generator-ish scripts (gen:*, or a --fix / --update mode), of which 10 are named as the gen of a driver-managed row. The
remaining 11 are the open set; several are already deliberately excluded
(gen:migration-registry, gen:authorable-surface-base, and the gen:test-typecheck-debt
family are all shrink-only or MIXED by declaration). The genuinely unaccounted candidates
are gen:sdui-lockstep, gen:openapi, gen:skill-refs, gen:skill-docs, gen:sbom, gen:react-blocks, and the per-package test-typecheck-debt.json copies outside packages/spec. ⛔ Not fixed here — one card, one route. Filed unassigned as #13731,
which also links #13335 (gen:skill-refs) as a previously recorded member of the
same class rather than a duplicate of it.
Verification
Gate family derived with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack
(no stale-tree warning) on d32b0f501; all 18 run.
16 green, including check:merge-driver, check:entry-guard, check:pm-dispatch-gates, check:turbo-task-graph, check:pnpm-filter-targets, check:agent-test-spelling, check:cross-package-test-inputs, check:parse-guard, and the census gate itself.
Also green beyond the derived list, because this PR adds a root manifest key: check-self-test-wired, check-self-test-workflow-commands, check-aggregator-roster, check-required-contexts, check:filter-alias-parity, check:nul-bytes, check:doc-anchors
(self-test + production leg each).
2 NOT MEASURED, neither a finding — both exit 3, the code these gates reserve for
a refusal: check-test-completeness ("there is no local log to hand it … ⛔ It is not a
red"), and check:dual-build-cjs-loads ("PREREQUISITE NOT MET — this gate reads built
output"; it needs a full pnpm build of 100+ packages). Declared narrowing: this PR's
root-manifest edit adds two keys to the scripts map of a private: true non-workspace
manifest that has no dist/ and no exports either gate reads, so neither can move.
CI runs both on a built tree.
Lint, narrowed with its evidence: 0 errors, 0 warnings over the 2 lintable changed
files. (1) The population comes from eslint's own config, which states and measures with
a positive control that this repo "never enables type-aware linting … for ANY file" — so
no untouched file's verdict can depend on this diff. (2) File count read from --format json: 2. (3) Invariance follows from (1). .gitattributes and package.json
are not eslint inputs.
Control-byte self-scan over all four edited files: clean.
Changeset
skip-changeset. This PR publishes nothing: zero packages/**, and the only manifest
touched is the root, which is private: true and not a workspace member. An empty
changeset is not the alternative here — check-empty-changeset rejects newly added ones
in this repo, and its own ledger records that the label is strictly safer.
Draft for the domain:devx seat to arm after review.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
dependenciesPull requests that update a dependency filesize/mskip-changesetPR has no user-facing published change; bypasses the changeset gate
2 participants
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes#13646
Both halves ship. But the load-bearing half turned out to already exist, and the
measurement that shows it also changes what the merge-driver half is allowed to be.
Verified on
d32b0f501. Diff is 4 files, +131/−1, and zero lines of.github/workflows/lint.yml— see "No workflow edit" below.⭐ Zone 2 falsified — and so is Zone 1's premise for half 1
Triage ruled that the load-bearing half is "一道「重生成并 diff」的 CI 检查", on the
grounds that it is the only instrument reaching the 13 anchors that went stale with no
conflict marker. That instrument is already in the tree, already required, and already
fires on exactly that case.
scripts/check-system-context-census.mjsre-derives the census from the tree with an ASTwalk and compares it to the committed page — its POPULATION check requires every read site
the census finds to be anchored at its exact
file:line. It runs in.github/workflows/lint.ymlas the joblint, whosename:is the required statuscontext
Lint & Repo Gates(node scripts/check-required-contexts.mjs), onpull_request+merge_group+push:main, with nopaths:filter.Reproducing the card's own silent case on
cc837dbfec— shiftplugin-sharing/src/sharing-service.tsdown 29 lines (main's real delta in the #13625window) and leave the page untouched, which is precisely the
branch-never-touched-that-file shape git merges clean:
Those are the card's own
+29values (625→654,891→920,978→1007,1568→1597,1309→1338) — the gate names every one of them. ⇒ The silent 13 are not silent to CI.What was actually missing: nothing asserted the gate is scheduled
check-self-test-wiredis conditional in the wrong direction for this — it requires thata script CI runs also has its
--self-testrun. Delete both invocations fromlint.ymland it goes green, silently retiring the only instrument that catches a staleanchor. Ablated, with the mutation confirmed on disk (2 invocations → 0):
The production run cannot see its own descheduling, which is exactly why the assertion
belongs in
--self-test. Added there, following the precedentcheck-doc-frontmatter,check-aggregator-rosterandcheck-ci-filter-parityset. Self-test now 37 cases, green.No workflow edit — deliberately
lint.ymlalready invokes both legs, so the pin reads the workflow instead of addingto it. That is the same move
check-doc-frontmatterrecords for its second docs root("
lint.ymlis the repo's busiest file and a second step would have been a thirdconcurrent edit of it"). ⇒ This PR does not touch
lint.ymlat all, so it does notcontend with #13584 and does not consume the slot #13582 is held for.
Half 2 — the merge driver route, scoped to the FILE
Registered in
scripts/regen-artifacts.mjs(the single source of truth) plus.gitattributes, withgen:/check:in the root manifest. This is the firstproduction row owned by ROOT tooling — it exercises the
ownerfield #13585 added,which until now only synthetic self-test cases touched:
content/docs/permissions/**. That glob is not safe: unlike the routed siblingcontent/docs/references/**, which is generated whole,content/docs/permissions/is22 hand-written prose pages around exactly one generated page. The directory route
would defer 21 prose files to OURS and drop the other side's edits silently — the exact
trade
packages/spec/src/migrations/registry.tsis kept out of the table for. Routed asthe file; the glob is recorded in
NOT_DRIVER_MANAGEDso the next author meets thereasoning instead of the omission.
The header's own warning, answered rather than accepted
os-regen-merge.shwarns that a routed path can "merge with exit 0 and zero conflictmarkers while SILENTLY DROPPING one side's changes". Here something still reddens: the
census gate above, on every PR, from a required job, re-deriving from the tree rather than
reading the page back. The driver removes hand-merge rounds; it is never the only signal.
⇒ Triage's ordering constraint ("第 1 项未落地前 ⛔ 不得合入第 2 项") is satisfied — the
CI instrument is in place before the routing, because it was already there.
Nor can the
genleg launder a population change. Injecting a new elevation read siteand running
--fix:--fixre-anchors a pure shift and REFUSES when a site arrived or vanished, so thepre-commit gate — which spawns
check, nevergen— stays red until a human writes the row.A2.1 cost and A2.2 determinism — both hold
node scripts/check-system-context-census.mjs)--fixround trip--fixon a clean tree--fixnew Date()/toISOStringin the script⇒ A2.1 holds (3s is not "minutes"; it was already affordable enough to be running). A2.2
holds — the output is a pure function of the tree, so the check cannot red on itself.
Scope question the card raised: which other generated artifacts are outside the routing?
Measured across all 79 manifests: 21 generator-ish scripts (
gen:*, or a--fix/--updatemode), of which 10 are named as thegenof a driver-managed row. Theremaining 11 are the open set; several are already deliberately excluded
(
gen:migration-registry,gen:authorable-surface-base, and thegen:test-typecheck-debtfamily are all shrink-only or MIXED by declaration). The genuinely unaccounted candidates
are
gen:sdui-lockstep,gen:openapi,gen:skill-refs,gen:skill-docs,gen:sbom,gen:react-blocks, and the per-packagetest-typecheck-debt.jsoncopies outsidepackages/spec. ⛔ Not fixed here — one card, one route. Filed unassigned as #13731,which also links #13335 (
gen:skill-refs) as a previously recorded member of thesame class rather than a duplicate of it.
Verification
Gate family derived with
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack(no stale-tree warning) on
d32b0f501; all 18 run.check:merge-driver,check:entry-guard,check:pm-dispatch-gates,check:turbo-task-graph,check:pnpm-filter-targets,check:agent-test-spelling,check:cross-package-test-inputs,check:parse-guard, and the census gate itself.check-self-test-wired,check-self-test-workflow-commands,check-aggregator-roster,check-required-contexts,check:filter-alias-parity,check:nul-bytes,check:doc-anchors(self-test + production leg each).
a refusal:
check-test-completeness("there is no local log to hand it … ⛔ It is not ared"), and
check:dual-build-cjs-loads("PREREQUISITE NOT MET — this gate reads builtoutput"; it needs a full
pnpm buildof 100+ packages). Declared narrowing: this PR'sroot-manifest edit adds two keys to the
scriptsmap of aprivate: truenon-workspacemanifest that has no
dist/and no exports either gate reads, so neither can move.CI runs both on a built tree.
files. (1) The population comes from eslint's own config, which states and measures with
a positive control that this repo "never enables type-aware linting … for ANY file" — so
no untouched file's verdict can depend on this diff. (2) File count read from
--format json: 2. (3) Invariance follows from (1)..gitattributesandpackage.jsonare not eslint inputs.
Changeset
skip-changeset. This PR publishes nothing: zeropackages/**, and the only manifesttouched is the root, which is
private: trueand not a workspace member. An emptychangeset is not the alternative here —
check-empty-changesetrejects newly added onesin this repo, and its own ledger records that the label is strictly safer.
Draft for the
domain:devxseat to arm after review.Generated by Claude Code
Generated by Claude Code