Repository navigation
Description
Measured for #13445 (dev seat, this measurement re-derived on origin/main at f532630d02 — re-derive rather than quote, this repo moves fast)
#13445 asked for a measurement, not a fix: supply a manifest to the runtime save gate in a probe, run it against the runtime corpus, count first-run findings and their true/false ratio, then write that reading plus the three candidates' blast radii here. Both are done below. #13445 closes as a consequence of this card existing.
The reading: 0/0 at the real gate, 232/0%-real if the gate were widened — and those are different questions
At the real production mechanism (evaluateRuntimeAuthoringGate → runRuntimeAuthoringRules, called with a real sduiManifest argument, confirmed reachable from a probe with zero production edits): 0 findings, always, for any input — not because the runtime corpus is clean, but because validateJsxPages — the only rule in the shared registry that reads ctx.sduiManifest — carries surfaces: CLI_ONLY (packages/lint/src/authoring-rules.ts) and is therefore excluded from runtimeAuthoringRulesFor()'s output for every metadata type by construction (r.surfaces.includes('runtime-publish') is false for it, full stop). This is machine-pinned (authoring-rule-wiring.test.ts pins runtimeAuthoringRulesFor('view')'s exact member list, which excludes it) and independently reproduced live: a probe drove a deliberately-broken kind:'html' page + the real manifest through the actual runtime-gate call shape for type:'page' — rulesRun came back ["validatePresetComparands"] (a different, legitimately-runtime-wired rule), never validateJsxPages; errors/advisories carried zero jsx-* entries.
Positive control (proves the harness/manifest are not the reason for the zero): calling validateJsxPages directly, bypassing the surface filter, on the identical broken page + identical real manifest returns 9 findings across jsx-forbidden-tag / jsx-mismatched-tag / jsx-unclosed-element — the rule and manifest are both live and working; only the runtime-surface wiring keeps them apart.
A2.2, falsified in the strong form the dispatch order flagged as possible: "the runtime corpus" — defined as the checked-in kind:'html'/'jsx' page items anywhere in this repo that a live PUT/save could ever write — is not merely similar to the authoring corpus, it is the identical 3 files (showcase_capability_map, showcase_command_center_jsx, showcase_start_here; confirmed by a repo-wide grep for kind: 'html'|'jsx' outside rule source/fixtures — nothing else exists). Running validateJsxPages directly against those 3 real pages with the real repo-root sdui.manifest.json reproduces packages/lint/src/sdui-jsx-baseline.json exactly — 13 rows, 232 findings, byte-identical breakdown — confirming both that the corpus is identical and that the ledger is not stale. Per that ledger's own recorded verdict (re-verified live, not re-adjudicated fresh): 0 of the 232 are real — "every error below is a plain HTML tag, none is a real authoring mistake." So the hypothetical "if validateJsxPages were widened to runtime-publish today, using only the manifest-supply fix" number is 232 findings / 0% real / 100% noise — the same 232, because it is the same corpus.
Paired, as asked: 0/0 (real mechanism, undefined ratio, nothing ran) vs. 232 findings / 0% real (hypothetical, same corpus, already-adjudicated ledger). Neither number is an argument for urgency on its own — the first says nothing is enforced today; the second says the existing first-run-noise problem #12924's ratchet-to-zero ledger was built to hold would recur unchanged if the surface question below were answered "yes" without also fixing the same public-tier-vocabulary gap objectui#6740 already tracks.
The reframing: the card's three candidates answer "where does the value come from," not "does the rule run at all"
#13445's three candidates (kernel-boot resolution / a published manifest in an existing dependency / an explicit deployment input) are all about sourcing sduiManifest. All three are necessary but none is sufficient — solving the sourcing question and wiring it through protocol.ts would still produce the 0/0 line above, unchanged, because validateJsxPages's CLI_ONLY surface is a separate, deliberately adjudicated boundary, not a wiring gap:
packages/lint/src/authoring-rules.ts,RUNTIME_HEAVY_SOURCE_PARSE: "Not runtime-safe: parses authored source through typescript/sucrase, the two dependencies the kernel boot path must never load (lazy-deps.test.ts). Studio compiles page source on its own path."
runtime-lazy-deps.test.ts pins the claim in three tiers, machine-checked against spawned processes reading the built dist/ (not a same-process assertion): typescript/sucrase (~9 MB) load never at the runtime surface — "not at import, not gating any type, with or without any authored artifact" — for exactly this reason. Lifting validateJsxPages onto runtime-publish would need to cross that boundary (or replace the rule's parser with something the kernel boot path is allowed to load), which is a second, independent architecture decision with its own blast radius — arguably the more consequential one, since it is a "may this ever run on the hot write path at all" question, not a "which of three plumbing shapes" question. This dev seat is not recommending an answer to it — flagging that #13445's framing (three candidates, one axis) undercounted the decision by one axis is itself the finding.
The three original candidates' blast radii, as measured (not restated)
| # | Candidate | Measured blast radius |
|---|---|---|
| 1 | Kernel-boot manifest resolution handed to the protocol | Wiring choke point is small: ObjectStackProtocolImplementation's constructor has exactly ONE production call site (packages/metadata-protocol/src/plugin.ts's assembleMetadataProtocol); an added optional positional/options param is backward-compatible with all 228 test call sites that construct it directly. Sourcing is the open problem: precedent exists for boot-time deployment-fact gathering threaded as pure arguments (organizationId, orgWallEnforced via resolveTenancyPosture() — called from 10+ files including packages/runtime/src/app-plugin.ts, packages/objectql/src/engine.ts, packages/cli/src/commands/serve.ts), but every existing case is a small env-derived boolean/string, not a multi-KB generated JSON artifact requiring filesystem or network access at boot — there is no existing analog for that shape, and the CLI's own cwd-based read is explicitly out (arbitrary server-side cwd; ruled out by #13445 1.4). |
| 2 | Published manifest inside a package the runtime already depends on | metadata-protocol's current deps (core, formula, lint, metadata, metadata-core, spec, types) — none ship this manifest today. The manifest is presently a cross-repo sync artifact: generated by loading a Playwright-rendered browser dump of objectui's built console app (scripts/gen-sdui-manifest.sh → packages/console/dist/sdui.manifest.json), pinned to .objectui-sha, sha256-verified and staleness-gated against that pin (scripts/check-sdui-manifest.mjs). Baking it into an existing dependency moves that generator/sync obligation onto that package's own release cadence — a new coupling axis metadata-protocol does not have today (currently only the CLI reads the always-current repo-root file, at run time, from disk). The one existing precedent for "ship it inside a dependency" — the CLI's own @objectstack/console/dist/sdui.manifest.json fallback — is independently re-confirmed broken here: packages/console/package.json's exports map is {"./package.json": "./package.json"} only, no . or ./dist/* entry, so ERR_PACKAGE_PATH_NOT_EXPORTED is not a transient issue, it is what the declared exports map guarantees. |
| 3 | Explicit deployment input | Established pattern, smallest mechanical surface: AssembleMetadataProtocolOptions already carries deployment-supplied posture flags this exact way (options.authoringChannel, options.runPlatformMigrations), both optional and safely defaulted; a sibling options.sduiManifest?: unknown would fit without a new mechanism. In practice only one production call site sets authoringChannel explicitly today (packages/objectql/src/plugin.ts, forwarding its own plugin option) — the real "who has to configure this" burden centralizes at the ObjectQLPlugin options layer rather than scattering per-deployment. Cost (as the original card already named, now sharper): an unset option must default to today's parse-only behavior — same "unstated posture must not manufacture a refusal" principle already coded for orgWallEnforced — so most tenants who never opt in get no behavior change, reproducing today's status quo for the silent majority. |
What remains for the maintainer
Two independent decisions, not one — and the second is prior in the sense that answering only the first (any of the three candidates) still yields the 0/0 line above:
- Should
validateJsxPages(or an equivalent, lighter check) ever run on theruntime-publishsurface, crossing thetypescript/sucrasekernel-boot-path banruntime-lazy-deps.test.tscurrently enforces absolutely — and if so, how (a lighter/pre-compiled parser? an async/deferred validation pass instead of a synchronous save-time gate? accept the ~9 MB load on this one path)? This is unmeasured by this card; it is a new architecture question the original three candidates did not anticipate. - If (1) is yes, which of the three candidates above sources the manifest — unchanged from [finding] the runtime save gate never receives a sduiManifest — the third independent cause of validateTree inertness, untouched by the #12924 wiring #13445's original framing, now with measured blast radii per candidate instead of estimated ones.
- Either way, arming it reproduces the 232-finding/0%-real noise problem [finding] nothing wires an sdui.manifest.json, so validateJsxPages runs parse-only and validateTree — including both ported lockstep diagnostics — is dead code in the production gate #12924's ratchet-to-zero ledger already holds for the CLI seam — the same public-tier-vocabulary gap (objectui#6740,
div/aabsent from the 57-block curated set) needs its own resolution or its own ratchet-to-zero ledger at the runtime surface before "armed" reads as "useful" rather than "noisy."
Refs
- [finding] the runtime save gate never receives a sduiManifest — the third independent cause of validateTree inertness, untouched by the #12924 wiring #13445 — the card this measurement was dispatched to close.
- [finding] nothing wires an sdui.manifest.json, so validateJsxPages runs parse-only and validateTree — including both ported lockstep diagnostics — is dead code in the production gate #12924 — the CLI/CI seam wiring (now returns HTTP 404; a deactivated GitHub account took it out of reach, per the Dangling-reference patrol: nothing detects an issue reference that fails to RESOLVE (as distinct from closed) — measured 6+ times, and a card's author is unreadable once it is unreachable #13634/The tenant-audit census issue 13178 is unreachable (404) while three open cards cite it as their input #13548 family — its prerequisites survive only via transcription in [finding] the runtime save gate never receives a sduiManifest — the third independent cause of validateTree inertness, untouched by the #12924 wiring #13445's own comment thread).
- objectui#6740 — the public-tier vocabulary gap (
div/aabsent) the 232/0%-real noise traces to. packages/lint/src/sdui-jsx-baseline.json,packages/lint/src/runtime-lazy-deps.test.ts,packages/lint/src/authoring-rule-wiring.test.ts,packages/lint/src/runtime-gate.ts,packages/metadata-protocol/src/runtime-authoring-gate.ts,packages/metadata-protocol/src/plugin.ts— sources this measurement is grounded in.
Generated by Claude Code
Activity
huangyiirene commentedon Sep 1, 2026
裁决:(1) 否 —— 现在不武装;绊线入册;本卡关闭 completed(维护者 2026-09-01,总监批 #26)
项目总监席 · session
session_01KGtaLpkW1mycWgkbSb3H6t· 维护者对本批逐字:「同意」。validateJsxPages(或等价检查)不上runtime-publish面 ——typescript/sucrase的内核 boot 路径禁令(三层 pin,对 spawned 进程验 built dist)是被刻意裁定的架构边界,⛔ 不为一个假设面收益 232 findings / 0% real 的检查打破它;运行时保存门维持 parse-only,CLI_ONLY边界维持;div/a进精选集或有自己的 ratchet-to-zero 台账)且 出现真实的保存路径编写消费者 ⇒ 问题 (1) 带新分母回决策箱;状态转移(同笔)
关闭 completed(测量已交付 + 裁决已记);摘
needs-user-decision;priority:p2domain:devx留卡。Generated by Claude Code