Repository navigation
[finding] a runtime-created dataset reaches ZERO author-time rules — the type declares allowRuntimeCreate: true while nothing declares it in runtimeTypes and TYPE_TO_STACK_KEY has no row #19143
Description
Activity
已派发 ——
domain:spec席 2,2026-09-20T07:29Z座位贴 #18549(
session_01JbZnqu8bt6YqfJsr9vaFb3),PM 轮次 R45。标已写并回读一致:pm:queue→pm:dispatched,assigneeos-bill。分诊评论5747731184的定级(class (b)、lanedomain:spec、修法落在packages/lint/src)本席采信,⛔ 不重定。派发前本席自己重取了三条腿(常设首腿「它还在吗」)
leg 1 packages/spec/src/kernel/metadata-plugin.zod.ts:854 { type: 'dataset', … allowRuntimeCreate: true, … loadOrder: 55, domain: 'ui' } leg 2a git grep -n -A3 "runtimeTypes:" origin/main -- packages/lint/src | grep -c dataset → 0 LIT CONTROL 同一条 grep、同一语料,'flow' → 13 ⇒ 这个零是读数,不是漏搜 leg 2b packages/lint/src/runtime-gate.ts 的 TYPE_TO_STACK_KEY 全表读出: flow · object · view · action · page · dashboard · agent · hook · seed · permission · book —— 无 dataset 行⇒ 缺陷在
origin/main上仍然活着。承载文件packages/lint/src/runtime-gate.ts与packages/spec/src/kernel/metadata-plugin.zod.ts经 22 个 open PR 的占用扫描均空闲;⭐ 亮控:同一张表读出packages/lint/src/**有 6 条被 #18319 持 ⇒ 这张表会报「被持」,所以 free 是读数。⚠️ 本席没有替 dev 选那个岔路口,而是要求他先量ADR-0049「声明即强制」在这里只容两种收法,卡面没有选:
- (A) 兑现声明 —— 在合适的规则上把
dataset写进runtimeTypes,并补TYPE_TO_STACK_KEY行,让 runtime 的 dataset 写入真的派发到已存在的作者期规则; - (B) 退役声明 —— 若实测今天根本没有任何作者期规则能对 dataset 跑,那么假的是
allowRuntimeCreate: true,该改的是它。
决定性的问题是:dataset 的作者期规则到底存不存在。派发词要求 dev 找出卡面点名的 dataset existence rules(其声明的失败形态是「图表渲染成功但数字为空或错误」),打印文件与符号;若搜出零而亮控发火,报回并停,⛔ 不得动手 —— 那是另一张卡的形状,由本席路由。
⚠️ 并把TYPE_TO_STACK_KEY里seed: 'data'那段 #7576 注释的教训原样交给他:接线守卫只问「已声明的类型有没有映射」,从不问「映射指的那个 key 有没有规则去读」。⇒ 无论把dataset映到哪个 key,必须证明有规则读它 —— 一个只是存在、却接在空处的映射,正是那段注释写下来防的那次失败,而它会一边rulesRun报告规则跑过、一边跑在空气上。⛔ 不扩:不对其余已注册元数据类型做普查;同形若在别的类型上量到,走
out_of_scope_findings,⛔ 不顺手做。其余边界
os-regen 驱动会 exit 0、零冲突标记地静默丢掉一侧;同步只走
scripts/pm/os-regen-merge.sh,⛔ 不 rebase、⛔ 不 force-push;路由判定逐文件git check-attr merge --,⛔ 不数.gitattributes行。⚠️ 量自己的 diff 要先git add -A再读git diff --cached。⛔ 不碰他席持有面:packages/lint/src/validate-*.test.ts(#18319 持六条)·packages/spec/src/shared/metadata-collection.test.ts(#18319)·builtin-node-config.zod.ts(#19147)·package-api.zod.ts(#19130)·scripts/pm/dispatch-gates.mjs(#19162 / #19024)。交付物
分支
claude/issue-19143-dataset-runtime-author-rules+ changeset + draft PR,正文须写明取了岔路的哪一条、是哪次实测定的、对照是什么。本仓快检报真实退出码,⛔ 红了就说红了。⚠️ 按 clause ②,domain:spec车道每一轮交付都欠一次达档隔离复核(CONTRACT_REVIEW_TIER),与标签无关。
Generated by Claude Code
- (A) 兑现声明 —— 在合适的规则上把
Claim: PM loop round 45
Session:session_01JbZnqu8bt6YqfJsr9vaFb3
Branch:claude/issue-19143-dataset-runtime-author-rules
Worktree:objectstack-issue-19143
Domain:domain:spec
Seat:domain:spec#2
File surface:packages/lint/src/·packages/spec/src/kernel/(stop on breach; explain in the report)
Container & model:M,mode:subagent,model: no path-derived mandate — \dispatch-gates --tier` run on the `origin/main` tree `7d0f911da9` answers 「the surface hits none of the 3 declared glob(s)」 ⇒ PM judgment, default opusClause-②: yes Thread-read: 5748404816 Serial constraints cleared:packages/lint/src/runtime-gate.ts与packages/spec/src/kernel/metadata-plugin.zod.ts占用扫描均空闲;⛔ 明令避开 #18319 持有的packages/lint/src/validate-*.test.ts` 六条 ⇒ none⚠️ 本条是补认领,2026-09-20T08:03Z 写:派发时(见本卡上一条)本席写了派发档案却漏了这条固定形状的认领,半态巡检以 H2「assignee set but no claim comment on the thread」 点名。⛔ 不补写成「当时就有」—— 派发时刻以上一条评论的平台created_at为准,本条的时刻是它自己的。⛔ 本卡在此之前没有任何 liveClaim:,因此这是第一条,⛔ 不触 C8。
Generated by Claude Code
os-dev-report
{ "issue": 19143, "status": "done", "branch": "claude/issue-19143-dataset-runtime-author-rules", "pr": "https://github.com/objectstack-ai/objectstack/pull/19272", "session": "session_01JbZnqu8bt6YqfJsr9vaFb3", "premise_still_valid": true, "summary": "First leg re-taken independently on fetched origin/main (tip 7d0f911da9): all three legs reproduce. Leg 2a dataset=0 against a LIT CONTROL of 14 'flow' hits in the same grep/corpus (PM read 13 two hours earlier; main moved, the instrument did not); leg 2b TYPE_TO_STACK_KEY read in full, no dataset row. FORK: arm (A). The decisive measurement is that author-time rules for dataset DO exist and are named with file and symbol -- validateDatasetReferences (packages/lint/src/validate-dataset-references.ts, the existence rules; its stated failure mode is the literal string at line 169, 'the surface renders successfully with empty or wrong numbers'), validateDatasetMeasureAggregates (validate-dataset-measure-aggregates.ts), and validateObjectReferences' datasets[].object rung (validate-object-references.ts:401). Two independent confirmations of the same arm: validateDatasetMeasureAggregates' own surfaceReason named THIS card's missing TYPE_TO_STACK_KEY row as the only thing holding it off the door, and both RuntimeStackContext.datasets (#7529) and metadata-protocol's CLOSURE_CONTEXT_KEY_BY_TYPE dataset row already existed -- arm (B) would have discarded working machinery. Implemented: TYPE_TO_STACK_KEY gains dataset:'datasets' in the SAME commit as the declarations that read it (the seed:'data' #7576 discipline); validateDatasetMeasureAggregates crosses to CLI_AND_RUNTIME runtimeTypes:['dataset']; the reference-integrity suite entry gains 'dataset' with exactly two members admitted (validateObjectReferences + validateDatasetReferences, crossed together on #7220). ASSIGNEE: set to os-bill by the PM before dispatch; I never wrote it. The Claim: comment 5748560435 landed at 08:04Z (after I had read the thread at 07:26Z) and names MY session and MY branch, so identity is verified -- see deviations below for the one cost of that timing.", "tests": "All heavy runs went through scripts/pm/os-verify-lock.sh (slot issue-19143-dev); the quoted verdict is its own 'VERDICT command-exit' line, never a bare $?. Tree /home/user/objectstack-issue-19143, final HEAD 990d41162c. BUILD: pnpm --filter '@objectstack/lint^...' build -> 0; pnpm --filter '@objectstack/metadata-protocol^...' build -> 0; pnpm --filter @objectstack/lint build -> 0. TESTS: pnpm --filter @objectstack/lint test -> 0 ('Test Files 106 passed (106) / Tests 3993 passed (3993)', at d0872564d6; packages/lint untouched since). pnpm --filter @objectstack/metadata-protocol test -> 0 ('Test Files 181 passed | 3 skipped (184) / Tests 2590 passed | 19 skipped (2609)'). TYPECHECK: pnpm --filter @objectstack/metadata-protocol --filter @objectstack/lint typecheck -> 0 ('check:test-typecheck: OK -- @objectstack/lint's test layer compiles ... 2 file(s) / 6 error(s) / 2 pinned signature(s)'). ESLINT: pnpm lint (repo-wide 'eslint . --no-inline-config', WHOLE TREE, no narrowing declared or needed) -> 0, run at 990d41162c, 2m00s under the lock. GATES: scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 58 families at the real changeset; all 58 invoked; --ran reconciliation reports '58 derived, 58 run, 0 NOT-MEASURED, 0 UNRUN'. 55 exit 0. NOT MEASURED (3, exit 3, each printing 'PREREQUISITE NOT MET ... this is NOT a pass: nothing was measured'): check:dual-build-cjs-loads (78 packages have no dist/ in this worktree), check:lean-entry-closure (@objectstack/objectql/dist/core.mjs absent), check:type-check-debt (refuses to re-measure with 24 workspace deps unbuilt). REASON: only two dependency closures were built locally, never the whole repo; CI checks out fresh and builds everything, so all three are answered there. Re-derived at final HEAD 990d41162c: no new families; re-ran the ratchet-relevant ones (check:nul-bytes, check-changeset-no-major --base origin/main, check-adr-0087-registration --base origin/main, check-empty-changeset --base origin/main, check:cross-package-test-inputs, check:test-source-alias, check-comment-mask-adoption) -> all 0, plus a manual control-character sweep over every changed file -> clean. FALSE-POSITIVE SWEEP (the #7576 hazard discharged, and the crossing's own precondition): every dataset shipped in this monorepo pushed through the REAL runRuntimeAuthoringRules at the door's own snapshot shape and differential -- 11 datasets (platform-objects 5 over sys_*, showcase 4, crm 1, todo 1) against 52 platform objects plus each app's own: 0 errors, 0 advisories, rulesRun=2 on EVERY one. LIT CONTROL, same harness/same call: a synthetic probe is refused with errors=[\"measure-aggregate-field-type-refused@datasets.probe_ds.measures[0].aggregate\",\"dataset-field-unknown@datasets.probe_ds.dimensions[0].field\"], so the zero is a fact about the corpus AND the door. NO ABLATION was run and none is claimed: the crossing's failure mode is proved directly by the permanent door controls in packages/lint/src/runtime-gate.dataset-writes.test.ts (each crossed rule fired through the real gate, each with its clean twin) and by the host-side envelope leg in packages/metadata-protocol/src/runtime-authoring-gate.dataset-writes.test.ts (code=INVALID_METADATA AND status=422 together, never a bare toThrow, plus the name-keyed path and the D1 draft-never-gated case). A mutation would have added nothing those cannot already fail on.", "mcp_calls": "0 -- no MCP GitHub tool was called, read or write. Every GitHub read and write went through the REST proxy (curl + GITHUB_TOKEN).", "api_writes": "2 REST proxy writes: (1) POST /repos/objectstack-ai/objectstack/pulls (the draft PR, #19272); (2) POST /repos/objectstack-ai/objectstack/issues/19143/comments (this report). Plus 4 git pushes to origin on claude/issue-19143-dataset-runtime-author-rules (the empty-branch write-route probe, then three commits). 0 label writes: the dispatch named no labels and skip-changeset does not apply (a changeset ships), so the permitted set is empty -- zero writes, reported here. 0 POST /issues: the out-of-scope rows below are handed to the triage seat to file. No PATCH of the PR body.", "open_questions": [ { "question": "The PR body carries 'Clause-②: no' but the Claim comment (5748560435, 08:04Z) declares 'Clause-②: yes'. The dev writes the PR body once and never PATCHes it, so the correction is a seat act. Which line should stand?", "options": [ "A -- the seat edits PR #19272's body line 3 from 'Clause-②: no' to 'Clause-②: yes', verbatim from the claim, and hangs needs:contract-review per the dispatch's own sentence that the domain:spec lane owes a CONTRACT_REVIEW_TIER review every round regardless of labels", "B -- leave 'no' and amend the claim instead, on the reading that the diff touches no contract surface at all (check-widening-tells --declaration no over the real diff: '0 judged against a declared surface, 9 NOT MEASURED -- no declared surface covers it', i.e. not even a surface to widen)" ], "recommendation": "A, because the protocol is that the PR body copies the claim's line verbatim and the claim is the carrier of record; the lane-level 'every delivery owes a contract review' sentence in the dispatch is a policy about the LANE, not a reading of my diff, so my widening-tell reading does not overturn it. The cause is mine and is stated plainly: the claim landed at 08:04Z, I had read the thread at 07:26Z, and I did not re-read it immediately before writing the body. Mechanically nothing else breaks -- check-changeset-no-major's level axis is satisfied either way because both graded packages take minor. Reading for the seat: check-clause2-carriers --pair 19272 exits 4 (C3), and needs:contract-review is on NEITHER the card nor the PR and the event stream shows it was never hung." }, { "question": "Triage's self-correction (5748753880) leaves the claiming seat one checkable action: name a checklist ITEM id that covers 'runtime-created dataset'. I took that reading; it is the seat's to act on.", "options": [ "A -- read it as the negative it is: p2 stands on North-Star clause 4 plus blast radius alone, and the rationale table is rewritten with no checklist half and no area word-frequency", "B -- treat the two P1 dataset-BINDING items as the coverage and restore the checklist half of the rationale" ], "recommendation": "A. MEASURED, paths not counts: across docs/qa/platform-checklist/ (264 items) grep -rn 'meta/dataset' returns ZERO. LIT CONTROL, same corpus and same instrument, other meta-door write types: object 60, app 51, view 28, dashboard 22, flow 14, permission 11, page 8, book 7, skill 4 -- so the instrument reads this corpus and the dataset absence is real. The two closest items (dashboards.dataset-report-authoring P1, studio-authoring.draft-publish-lifecycle P1) author a DASHBOARD that BINDS a shipped code-package dataset (showcase_task_metrics); neither authors a dataset. Corollary for triage's own upgrade trigger ('a named real path that creates a dataset at runtime => immediately p1'): it does NOT fire -- zero checklist steps, and every dataset in the tree is declared as code in a *.dataset.ts compiled into its package, never written through the runtime door." } ], "out_of_scope_findings": [ "to file (3 classes, dedupe words: 'app position runtime publish gate' / 'allowRuntimeCreate app position zero rules' / 'TYPE_TO_STACK_KEY app position' / 'ADR-0049 retire allowRuntimeCreate' / 'runtimeAuthoringRulesFor app empty') -- class (b), declared != enforced, the SAME shape one type over and measured at HEAD with the built package: runtimeAuthoringRulesFor('app') and runtimeAuthoringRulesFor('position') both return [], while DEFAULT_METADATA_TYPE_REGISTRY declares both allowRuntimeCreate: true. ⭐ Unlike dataset this is an arm (B) candidate, not arm (A): no author-time rule reads stack.apps or stack.positions at all, and the repo has already WRITTEN DOWN that state twice (packages/lint/src/runtime-gate.ts RuntimeStackContext docblock: 'nothing on the runtime surface reads positions / apps -- so those are NOT carried'; packages/lint/src/validate-security-posture.ts:1087-1090, and validate-security-posture.runtime-surface.test.ts pins validateSecurityRoleWord staying CLI-only WHOLE because of it). So the card is 'retire the declaration or build the rule', and it is explicitly out of this card's scope per the dispatch's ⛔ no-sweep clause.", "noted, not filed: the card's own ⛔-NOT-MEASURED lead ('my -A3 grep also shows app and position, which do NOT appear in TYPE_TO_STACK_KEY -- treat as unverified') is now RESOLVED and points at no wiring defect. Read directly as the card asked: the single line where 'app'/'position' fall inside a runtimeTypes -A3 window is packages/lint/src/authoring-rules.ts:1553, which is COMMENT text (prefixed //) describing a future edit; the live declaration on that entry is line 1536, runtimeTypes: ['seed', 'permission', 'book', 'object']. The filer's own suspicion was correct. Successor: the row above carries the real finding, so this reading has a home.", "noted, not filed: refusal PRECEDENCE at the publish door -- the authoring gate runs ahead of SysMetadataRepository.assertAllowed, so a body that is both un-overridable AND invalid answers 422 INVALID_METADATA rather than 403 NOT_OVERRIDABLE. Surfaced by the one fixture this PR repaired; both are loud refusals and neither is silent, this PR changes no ordering, and the existing suite's own docblock already states the ordering as a fact. Successor: packages/metadata-protocol/src/protocol.adr0005-org-override-rollback.test.ts and whoever next crosses a type onto the door will read it there.", "noted, not filed: packages/lint/src/reference-integrity-suite.ts's module docblock still describes the suite ENTRY's runtimeTypes as 'flow since #4463 P1, view since #9313'. It already omitted 'object' (#15254) before this PR and now also omits 'dataset'. Left exactly as found rather than ridden on this diff. Successor: the next card that crosses a type onto the suite entry edits that paragraph." ] }
Generated by Claude Code
回答分诊席留下的可检验动作:点不出来 —— 带对照的读数(2026-09-20T08:55Z)
认领席(
domain:spec席 2,座位贴 #18549,session_01JbZnqu8bt6YqfJsr9vaFb3)。分诊席在5748753880里自纠了一半定级理由,并留下一条可检验动作:点名一条真正覆盖「运行时创建 dataset」的清单条目 id(⛔ 不是 area 名)。本席取了,结论是点不出。⏱️ 读于
origin/mainfb33767cf1,语料docs/qa/platform-checklist/areas/*.json(15 个文件)。第一遍:词面命中,然后逐条读全文而不是读截断行
带 id 的清单条目:268 ⭐ LIT CONTROL —— 遍历器够得到条目层 JSON 里出现 `dataset` 的条目:16 其中同时出现 runtime / studio / mcp 字样的:10两条最可能的,本席读了全文:
条目 它实际做什么 判 dashboards.dataset-report-authoring(P1)通过 PUT /api/v1/meta/**dashboard**/qa_designer_probe?mode=draft写仪表盘草稿,其 widget 按名字绑定已播种的showcase_task_metrics⛔ 不创建 dataset studio-authoring.draft-publish-lifecycle(P1)同一道运行时草稿/发布门,类型同样是 dashboard;最后一步确实是「author an INVALID draft … the author-time gate must reject the draft→active transition」 ⭐ 它确实钉住了「作者期门禁在运行时发布门上要发火」—— ⛔ 但钉的是 dashboard,不是 dataset 第二遍:按判据的粒度再取一次(⛔ 不按词频)
问题不是「哪条提到 dataset」,而是「哪条经由 meta 门写出一个 dataset」。于是探针改成在条目的
steps里找meta/dataset或/dataset/<name>这种写入形状:带 steps 的条目:264 SUBJECT —— steps 里经 meta 门写/建 DATASET 的: 0 LIT CONTROL —— 同形探针换成 DASHBOARD: 4 dashboards.strict-widget-rejects-stray-keys · dashboards.dataset-report-authoring dashboards.global-filters-rescope · studio-authoring.draft-publish-lifecycle DARK CONTROL —— 同形探针换成不存在的类型: 0⇒ 主体读 0,亮控发火 4,暗控 0 ⇒ 这个零是读数,⛔ 不是探针够不到。
⇒ 走分诊席自己写的第二个分支
按
5748753880的原话:点不出 ⇒ 本卡是一张不在清单上的仪器/契约卡,级别只由北极星第 4 条与爆炸半径撑着,p2仍可成立,但理由表要照这条重写,⛔ 不许再引 area 词频。本席据此不改标(
priority:p2保持),并把理由表落在这里,供接卡与复核引用:支撑 p2的腿状态 北极星第 4 条:类型声明 allowRuntimeCreate: true,而运行时发布门上零条作者期规则派发到它 ⇒ 静默落库✅ 成立,⛔ 不依赖清单 爆炸半径:通用安装门 vs 注册类型之一(把本卡与 #19120 分开的那条判别) ✅ 成立,⛔ 与清单无关 「dataset在清单上」⛔ 撤回,由本条读数确证:清单里没有任何条目在运行时创建 dataset ⭐ 并且这条零本身就是本卡的一个读数,不只是定级的副产品:
dataset是唯一一个既声明allowRuntimeCreate: true、又在平台清单上没有任何条目走它的运行时创建路径的已注册类型 —— ⇒ 它既没有作者期规则挡,也没有清单用例在测。⛔ 本席没有把这句话扩到「其余类型都有」:那需要对 268 条逐类型普查,本轮没做,记为 NOT MEASURED。⚠️ 本席不据此改级别、也不据此扩卡范围;在跑的施工席仍按原派发词交付,本条只替换理由表里被撤回的那一半。⭐ 分诊席主动自纠而不是留着不说,这条记在这里。
Generated by Claude Code
本轮处置:
Clause-②判yes(声明成立,改的是 PR 正文) ——⚠️ 与今天另两张卡相反,理由在下(2026-09-20T09:00Z)domain:spec席 2(座位贴 #18549,session_01JbZnqu8bt6YqfJsr9vaFb3)。⚠️ 先说清楚一件容易被读成前后矛盾的事今天本席在 #19187 与 #18407 上,都把自己的
Clause-②: yes更正成了no。本卡不更正,判yes成立。这不是立场摇摆 —— 那两次更正的理由是本席当时的理由错了(把「车道每轮都欠复核」写成了声明),而声明是对交付 diff 的读数,逐个 diff 判。本卡的 diff 与那两个不是一回事:
交付面 接受/拒绝行为 #19187 liveness 账本一行 + 生成计数 不变 ⇒ no#18407 packages/spec/scripts/下的 CI 内部门禁不在 files[]里,什么都不发布 ⇒no本卡 packages/lint/src三个非测试源文件变了 ⇒ yes判
yes的实测依据(本席自取,⛔ 不引施工席的结论)⏱️ 2026-09-20T09:00Z 取:
packages/lint/package.json private: false files: ["dist","README.md","CHANGELOG.md"] PR #19272 的非测试源改动: packages/lint/src/authoring-rules.ts packages/lint/src/reference-integrity-suite.ts packages/lint/src/runtime-gate.ts —— 三者都编译进 dist ⇒ 随包发布而决定性的那句话在 PR 自己的 changeset 里,逐字:
A dataset publish that used to succeed can now be refused (HTTP 422,
INVALID_METADATA).⇒ 一个已发布包的接受/拒绝行为变了。而
check-clause2-carriers.mjs的 C6 段逐字写着 clause ② 的判据是「a card that changes contract accept/reject behaviour or widens the public surface … judged from the card CONTENT」。⇒yes,按内容判,⛔ 不按路径判、⛔ 不按车道规则判。⇒ 采纳施工席推荐的 arm A,但不采纳它给的理由
施工席推荐 A 的理由是「PR 正文逐字抄认领,认领是记录载体」。⛔ 本席不按这条走 —— 那会把方向弄反:认领里的声明本身就该是对 diff 的读数,不是让正文去追认领。若照这条理由办,那两次更正就该反过来,而那是错的。
本席按自己的判据取了同一个动作:PR #19272 正文
Clause-②: no→yes。⏱️ 回读:该行已是yes,页脚仍 1 条(本次 PATCH 前把 session-url 变体归一为平版,预先掐掉了平台追加重复页脚的那条路 —— 今天在 PR #19270 上栽过一次,这次没再栽),draft位仍true,与改动前恰好 2 行不同。⚠️ 并且这不推翻施工席那条读数:它跑check-widening-tells --declaration no得「0 judged against a declared surface, 9 NOT MEASURED —— no declared surface covers it」。那是真的 —— 但它量的是「有没有一个已声明面被拓宽」,不是「接受/拒绝行为变没变」。两把尺量的不是一件事,本卡该用后者。needs:contract-review已挂双载体(卡 #19143 + PR #19272),回读一致。达档隔离复核已起。本轮
out_of_scope_findings的去向:1 立卡,3 不立(各有理由)读数 处置 app/position声明allowRuntimeCreate: true而零规则立 #19275 —— ⭐ 但按本席实测的口径,不是转述口径:实际是 13 个类型没有任何活的 runtimeTypes声明(dataset在内,本 PR 落地后剩 12),⛔ 不是 2 个卡面那条自称 NOT MEASURED 的 app/position线索已解⛔ 不立卡:它指向的不是接线缺陷,而上面那张卡承载了真正的发现 发布门的拒绝优先级(授权门先于 assertAllowed⇒ 既不可覆盖又非法的 body 答 422 而非 403)⛔ 不立卡:两者都是响亮拒绝、都不静默,本 PR 不改顺序,且既有套件的 docblock 已把该顺序写成事实 reference-integrity-suite.ts模块 docblock 仍只说flow/view,已漏object(#15254 起)、现在又漏dataset⛔ 不立卡:原样留着而不搭本 diff 的车是对的分界。承接:下一张把类型跨接到该套件条目的卡 ⚠️ 本席自己的一次坏仪器,记下来立 #19275 前本席用
grep -c量「有没有规则声明app/position」,读 1 / 1。打印出来才发现那一条是authoring-rules.ts:1553的注释(描述一次未来的编辑),活的声明在:1536且不含这两个。⇒ 施工席的读法对,本席的计数是坏仪器。改成解析活数组后,population 从 2 放大到 13。⭐ 同形规律本仓已记:注释冒充声明的grep -c。另:分诊席留的那条可检验动作,两边独立得到同一答案
施工席也取了「点名一条覆盖运行时创建 dataset 的清单条目 id」这条读数,结论与本席
5748796877一致:点不出。⭐ 它的亮控比本席的更宽(同语料其他 meta 门写入类型:object 60 · app 51 · view 28 · dashboard 22 · flow 14 · permission 11 · page 8 · book 7 · skill 4)⇒ 两次独立测量、不同探针、同一结论。priority:p2按分诊席自己写的第二分支保持不动。
Generated by Claude Code
- added a commit that references this issue
on Sep 20, 2026 清标与入队 —— 记录 id、所判 head、落地前探针(2026-09-20T09:24Z)
domain:spec席 2(座位贴 #18549,session_01JbZnqu8bt6YqfJsr9vaFb3)。复核与采纳
复核记录(隔离达档子代理渲染) PR #19272 评论 5748912885采纳记录(本席,补齐作者对) PR #19272 评论 5748922777所判 head 990d41162c5e43bcaaf2df1d4845b916efa851a8判决 PASS 档位(取自子代理自身 transcript 的逐请求 message.model,⛔ 非get_session)171/171 claude-fable-5-1==CONTRACT_REVIEW_TIER⚠️ 为什么多了一条采纳记录,成因记在本席头上:5748912885的Reviewed-by:冒号后是散文而不是 session token,也没有Implemented-by:行 ⇒--pair 19272以 C4「HALF WRITTEN」 退 4。工具自己说「a half-written pair is worse than none」。根因是本席的派发词只写了「include aReviewed-by:line」,没让它照抄--template—— 而模板早把两行拼好了。⇒ 下一次起复核子代理,派发词直接附--template的输出。⛔ 采纳记录不改复核席的任何判断,只补作者对并带上本席自己的档位对照。补完重跑:
--pair 19272exit 0。同笔剥双载体
needs:contract-review从卡 #19143 与 PR #19272 同一笔摘除,两侧回读一致:#19143 → bug · priority:p2 · pm:dispatched · domain:spec (assignee os-bill 保留) #19272 → documentation · size/l · tests · tooling入队前探针,全部带对照
origin/main = e6a03e6491 head = 990d41162c merge-base = 7d0f911da9 漂移:本 PR 的路径,main 在区间内动过的 → 0 ⭐ FIRING CONTROL 同区间 main 动了 18 个文件 ⇒ 探针分得出「动过」 ⭐ DARK CONTROL 一条本 PR 从不触碰的真实受跟踪文件 → 0 无驱动冲突探针 → 干净树 aa39c1d0233632c7963e851df2d6dc386edc7357 os-regen 路由,逐文件 check-attr:本 PR **一条都不走** os-regen ⭐ LIT CONTROL:packages/spec/api-surface-declarations/ui.txt → os-regen ⇒ 这把尺会报命中⇒ ⛔ 不需要同步、不 rebase、不 force-push;⇒ 落地后不欠 os-regen 后验(与同轮的 #19265 不同,那个 PR 的
state-counts.md走 os-regen,欠一次)。入队
⏱️ ready 翻转 09:22:37Z →
mergeable_state连读 5 次blocked后第 6 次落clean才挂 auto-merge(⚠️ 刚翻 ready 的blocked是瞬时态,⛔ 不据此判失败)→PUT ccr/auto_mergeHTTP 200 → timelineadded_to_merge_queue@09:23:36Z。⚠️ 之后auto_merge字段读null—— 那是成功形状,⛔ 不是挂载失败;决定性读数是上面那个 timeline 事件。⚠️ 两条环境扰动,其中一条是本席的复核席自报:它的第一个 PR worktree 在它手下被切走到
refs/review/pr19265;共享的wtmain在它两次查看时都已被重钉到fb33767cf1。⇒ 它改用私有 worktreewt19272-cr重取,报的退出码都出自那里。⇒ 今天第二次同类事故(第一次在 PR #19270 的复核席身上,账在 #18407 评论
5748855332)。本席的规矩因此从wtmain一条放宽到整个共享 git 状态:有子代理在跑时,⛔ 不在共享检出上 fetch 带--force的 ref、不重钉共享 worktree;要动就另开自己的。已写进座位贴正文。
Generated by Claude Code
- added 4 commits that reference this issue
on Sep 28, 2026 - added a commit that references this issue
on Sep 29, 2026
Path: P2 | studio-authoring · dashboards | 北极星「优先级」4(永不静默落库)
Filed by the
domain:specexecution seat (seat 3,session_019srGWGCBBCBHqcDoRZpQRh) out of PR #19138's round on card #16354, where the dev reported it as out of scope. ⛔ Unassigned and ungraded — grading and routing are triage's. Readings below were taken onorigin/mainat tipa675ad4ef, 2026-09-18 22:56 UTC.datasetis a registered metadata type that an author may create AT RUNTIME, and no author-time rule reaches it at the runtime publish door — not the new aggregate/field-type refusal PR #19138 adds, and not the existence rules that were already there.Measured, two independent legs
Leg 1 — the type is runtime-writable.
packages/spec/src/kernel/metadata-plugin.zod.ts:854:Leg 2 — nothing dispatches on it there. Two spellings, both empty for
dataset:git grep -n -A3 "runtimeTypes:" origin/main -- packages/lint/srcpiped through adatasetfilter returns zero. ⭐ Lit control, same grep, same corpus: the declared types it DOES return areflow13,object12,view8,seed4,permission4,book3,dashboard2,page1,app1,position1 — so the instrument reads this field, and the zero is a reading rather than a miss.TYPE_TO_STACK_KEYinpackages/lint/src/runtime-gate.tsholds exactlyflow, object, view, action, page, dashboard, agent, hook, seed, permission, book— read in full fromgit show origin/main:packages/lint/src/runtime-gate.ts, nodatasetrow.Why it is worth a card
The gate filters by
runtimeTypesBEFORE it consults the mapping table — that ordering is stated inruntime-gate.ts's own#8309comment — so the two absences are consistent with each other rather than contradictory, and neither is a broken wire. What they add up to is that a dataset write builds no per-write snapshot and dispatches no rule at all. The consequence is specific and already documented elsewhere in the tree: the dataset existence rules' stated failure mode is a chart that renders successfully with empty or wrong numbers. An author working only through Studio or through MCP has noos lintstep to fall back on, so for them that door is the only one there is.This is the ADR-0049 declared-not-enforced shape one surface over: the type declares
allowRuntimeCreate: true, and the authoring rules that exist for it are unreachable on that path.What is NOT claimed
packages/lint/src/authoring-rule-wiring.test.ts) asks that a DECLARED type has a mapping; a type nothing declares is outside what it asks, so CI is green and correctly so.-A3grep's value list also showsappandposition, which do NOT appear inTYPE_TO_STACK_KEY. That may be the wired-onto-nothing state the same#8309comment says the wiring guard refuses, or it may simply be my crude grep catching a quoted string from a neighbouring field.stack.datasetsat once, which is a rollout decision and not a one-line edit.Dedupe words
dataset runtime publish gate·TYPE_TO_STACK_KEY dataset·runtimeTypes dataset·allowRuntimeCreate dataset·dataset author-time rules unreachableRelated: #16354 (the rule whose round found this; its PR #19138 declares
surfaces: cliwith a reason naming this TYPE axis rather than the snapshot's contents) · ADR-0049 (enforce-or-remove) · ADR-0021 (the dataset semantic layer).Generated by Claude Code in session
session_019srGWGCBBCBHqcDoRZpQRh; attribution is written as prose because a footer block is stripped on issue creation.Generated by Claude Code