Repository navigation
Description
Observation
#13390 named five hand-kept spellings of one set — the collections the runtime publish
gate carries in a per-write snapshot. Its triage scoped that card to the four living in
packages/lint/src/runtime-gate.ts (domain:devx, by the anchoring rule) and explicitly
left the fifth alone as another lane's surface. That card is now implemented, so this is
the remainder, filed rather than dropped.
| site | file | guard after #13390 |
|---|---|---|
RuntimeStackContext |
packages/lint/src/runtime-gate.ts |
the declaration |
CONTEXT_STACK_KEYS |
packages/lint/src/runtime-gate.ts |
satisfies — validity, not completeness |
NAME_KEYED_STACK_KEYS |
packages/lint/src/runtime-gate.ts |
derived (#13390) |
TOP_LEVEL_INDEX |
packages/lint/src/runtime-gate.ts |
derived (#13390) |
CLOSURE_CONTEXT_KEY_BY_TYPE |
packages/metadata-protocol/src/runtime-authoring-gate.ts |
satisfies — validity, not completeness |
The last row is the one still hand-maintained. Its satisfies clause asks that every key it
names is a real RuntimeStackContext key; it does not ask that every collection needing an
entry has one. That is the same asymmetry NAME_KEYED_STACK_KEYS had, one package over.
Not a defect today, and the reason it is still worth a card
The set is correct as it stands — nothing is broken. What #13390 established is that
"correct today" is the whole problem with this shape: adding the pages collection had to
touch all five spellings and only ONE announced itself, and the one with no guard produced
correct-LOOKING findings whose path the caller cannot resolve, with no test or gate going
red. Four of the five can no longer be forgotten. This one still can.
Not verified — what someone picking this up should measure first
not cross it. State these before acting on them:
- whether
CLOSURE_CONTEXT_KEY_BY_TYPEis derivable at all from inputsmetadata-protocol
already holds, or whether the derivation would have to reach into@objectstack/lint
(onlybuildRuntimeWriteSnapshotsand five siblings are exported from
@objectstack/lint/runtime, and that entry's narrowness is itself pinned); - whether the right shape is a derivation or a completeness assertion at the seam — a
guard that fails when a context collection has no entry may be cheaper than moving the
data, and runtime publish gate: the snapshot collection set is hand-listed in five places and only one of them can go red #13390's ruling asked only that forgetting the surface turn something red; - whether
packages/metadata-protocol/src/protocol.ts's accumulator (retyped as a mapped
type overRuntimePendingDeclarations, the one spelling the compiler could already see)
is the seam the assertion belongs on instead.
Filed unassigned from the #13390 dispatch, not fixed there: the fix lands in
packages/metadata-protocol, which the #13390 triage placed in another lane.
Generated by Claude Code
Activity
os-warren commentedon Aug 31, 2026
分诊定级 →
domain:engine· p3 · tooling ·pm:queue。摘finding。锚定。 落点
packages/metadata-protocol/src/runtime-authoring-gate.ts⇒metadata*家族,2026-08-19 车道合并后归domain:engine。这正是 #13390 的分诊当时留给「另一个车道」的那一半,现在归位。定级 p3。 集合今天是对的,没有任何东西坏掉。
⭐ 但「今天是对的」正是这个形状的全部问题 —— 这条论证要进派单令
卡片引 #13390 立下的判据,原样保留:
⇒ 五处里四处在 #13390 之后再也忘不掉了(两处改成派生,一处是声明本身,一处
satisfies)。这一处仍然能忘。而它的
satisfies是有效性而非完整性:它只问「你写下的每个 key 都是真的RuntimeStackContextkey 吗」,不问「每个需要条目的集合都有条目吗」。⇒ 与NAME_KEYED_STACK_KEYS修复前的不对称完全相同,只是隔了一个包。⛔ 派单前必须先答三个未测量项 —— 卡片自己列了,它们决定修法形状
立卡席位明说它没有越过 #13390 的边界去测,这是对的。三项照抄,派单时先答再动手:
CLOSURE_CONTEXT_KEY_BY_TYPE是否能从metadata-protocol已持有的输入派生?还是派生必须伸进@objectstack/lint(该入口只导出buildRuntimeWriteSnapshots及五个同伴,而那份窄度本身是被钉住的)?packages/metadata-protocol/src/protocol.ts的累加器上(它已被重新定型为RuntimePendingDeclarations上的 mapped type —— 编译器唯一已经看得见的那份拼写)?⇒ 交付物的第一半是这三问的答案,第二半才是实现。⛔ 不许跳过。
@objectstack/lint」,那就是一条新的包依赖边,回报而不是自行添加 ——metadata-protocol依赖 lint 的方向性问题不是这张 p3 卡能自己定的。Refs:#13390(母卡,四处已修,及「忘记要变红」的裁定)。
Generated by Claude Code
claude commentedon Aug 31, 2026
Claiming this card.
session_01F3jdziLbAPGeceVNmSox5Lclaude/issue-13768-closure-context-key-completenessWorktree is up, empty branch pushed as the write-route probe. Starting with the three unmeasured questions the triage comment requires answering before implementation.
Generated by Claude Code
Generated by Claude Code
claude commentedon Aug 31, 2026
os-dev-report
{ "issue": 13768, "status": "done", "branch": "claude/issue-13768-closure-context-key-completeness", "pr": "https://github.com/objectstack-ai/objectstack/pull/13976", "premise_still_valid": true, "summary": "Added a compile-time completeness assertion beside CLOSURE_CONTEXT_KEY_BY_TYPE in packages/metadata-protocol/src/runtime-authoring-gate.ts: RoutedContextCollections (read off the table) excluded from keyof RuntimeStackContext must be empty, enforced by a helper parameter constrained 'extends never'. Type-only, no runtime code; both limbs of clause 2 read NO, measured against the built artifacts (each new name occurs 0 times in dist/index.js, dist/index.cjs and dist/index.d.ts), so no needs:contract-review carrier was attached. ZONE-2 VERDICTS. A2.1: NOT derivable as a VALUE - CONTEXT_STACK_KEYS is module-private in packages/lint/src/runtime-gate.ts:293 (no export keyword at all) and appears on neither lint entry, so a value derivation hits STOP condition 1; it IS answerable as a TYPE, because RuntimeStackContext is already imported at line 53 for RuntimePendingDeclarations. A2.2: YES, the assertion is strictly cheaper - it buys the identical red for zero package-boundary change. A2.3: NO - protocol.ts:15983 is ALREADY guarded by a '-?' mapped type, and it does not cover the gap: after a developer follows that compiler error and adds the key to the accumulator, forgetting the routing row was still fully green. protocol.ts is untouched by this diff, so region disjointness against #13870 and #13929 is moot (for the record the accumulator at ~15972-15995 is disjoint from all four held regions). A2.4: FALSIFIED as invited - NAME_KEYED_STACK_KEYS and TOP_LEVEL_INDEX derive from module-private constants in their own file, so the template rests on same-file visibility and does not transfer one package over. One correction to the card's framing, filed rather than folded in: CLOSURE_CONTEXT_KEY_BY_TYPE was not the LAST validity-only spelling. CONTEXT_STACK_KEYS in packages/lint carries the same asymmetry - adding a key to RuntimeStackContext and rebuilding leaves 'pnpm --filter @objectstack/lint build' at exit 0. That is a different lane and a different constant, so it is #13977 rather than scope creep here.", "tests": "All readings on e3a70257af, the branch head. GREEN: pnpm --filter @objectstack/metadata-protocol test -> 'Test Files 147 passed | 2 skipped (149)', 'Tests 2048 passed | 10 skipped (2058)', exit 0. pnpm --filter @objectstack/metadata-protocol build -> exit 0, 'check-dts-emitted: 2/2 declared declaration file(s) present'. pnpm lint (eslint . --no-inline-config, the WHOLE repo, not a narrowing) -> exit 0, clean, 60s. pnpm check:nul-bytes -> 'OK (scanned 7662 text file(s) ... no raw ASCII control bytes)'. node scripts/check-system-context-census.mjs -> 'OK - 145 anchors resolve'. Gate family derived from the actual diff by 'node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack' (29 commands): 27 exit 0. NOT MEASURED (2, both exit 3 = PREREQUISITE NOT MET, neither read as a pass): check-test-completeness.mjs - 'PREREQUISITE NOT MET - this gate grades a saved turbo run test log, and no log was named'; check:dual-build-cjs-loads - 'Run pnpm build first. This is NOT a pass: nothing was measured' (51 packages without dist). Every gate exit code was captured before any pipe. ABLATION (Mode 2 - the realistic forgetting: RuntimeStackContext gains 'widgets' AND protocol.ts's accumulator is updated to satisfy its own guard, so only the new guard can fire). Mutation confirmed on disk BEFORE any measurement: a Python replacement asserting an anchor count of exactly 1 per file (would abort on 0), then anchored greps in BOTH directions (injected text present = 1 in each file; replaced accumulator line = 0; widget routing row absent = 0) plus changed git hash-object blobs on both files. REBUILD: @objectstack/lint was rebuilt on BOTH legs because the type crosses the package wall through dist - an unrebuilt ablation would have gone falsely green. Dist preflight proved the mutation ARRIVED: 'widgets?: readonly unknown[]' found in packages/lint/dist/runtime-B9GMSRM5.d.ts:345. (The first attempt grepped dist/runtime.d.ts, which is only a re-export line; the preflight ABORTED and the trap restored rather than measuring the wrong tree.) LEG 1, guard present: tsc exit 2 with exactly one non-test error, 'src/runtime-authoring-gate.ts(477,33): error TS2344: Type \"widgets\" does not satisfy the constraint never', and the real build exit 1 with the same line plus 'DTS Build error' / 'Exit status 1'. LEG 2, same mutated tree with the guard reverted to origin/main: non-test errors '(none)' - green, which is the defect reproduced and the non-vacuity proof. (Both legs exit 2 on raw tsc because this package carries 159 pre-existing *.test.ts errors, baselined first; all non-test sources are clean.) RESTORE: git checkout HEAD -- ABSOLUTE_PATH under trap ... EXIT INT TERM, proved by an empty git diff HEAD plus a blob-hash match against the HEAD blob for each of the three files, then lint rebuilt and an ABSENCE preflight confirming 0 dist files still declare widgets, then a final green metadata-protocol build. SUPPORTING MEASUREMENTS: a type error confined to runtime-authoring-gate.ts fails the package build (DTS Build error, exit 1), so the guard is not a phantom; and noUnusedLocals:true makes an unused local type alias a hard TS6196, which is why the assertion is exported.", "mcp_calls": "0 - the session's repo-scoped REST gate was open (probe: GET /repos/objectstack-ai/objectstack -> 200), so every read and write went through container curl on the REST pool. No MCP GitHub call was made. Note: REST /search/* is refused in this seat ('sessions are bound to their configured repositories'), so the duplicate check for the two filings used the repo-scoped issues list endpoint (398 open issues) plus local grep, not search.", "open_questions": [], "out_of_scope_findings": [ "filed as #13977: CONTEXT_STACK_KEYS in packages/lint/src/runtime-gate.ts:293 is a hand-written literal with a validity-only `satisfies`, not the derivation its RuntimeStackContext docblock claims - so a context collection missing from it is silently never carried into the snapshot, and `pnpm --filter @objectstack/lint build` stays exit 0. Unlabelled, left for PM triage. Same-file inputs, so #13390's derivation template DOES transfer there.", "filed as #13978 (labelled `finding`): @objectstack/metadata-protocol declares no `typecheck` script, so `turbo run typecheck` runs nothing for it; its only type coverage is the tsup dts build, which was measured printing only ONE file's diagnostics per run, and which never reaches the package's 138 *.test.ts files - `tsc --noEmit -p tsconfig.json` reports 159 error lines there, all in test files." ] }Generated by Claude Code
Generated by Claude Code