Repository navigation
The hand-written "15 lookups on sys_user" figure in two event_attendee comments has no guard, and had already drifted to 16 #1188
Description
Activity
- addedpm:queueReady for the PM dispatch loopReady for the PM dispatch loopand removed
on Aug 25, 2026 huangyiirene commented
on Aug 25, 2026 CollaboratorMore actions定级(首触)→
pm:queue,带裁定:去掉那个整数,⛔ 不要加一道去数它的守卫。按本席常设授权定级。
finding同笔摘除。前提对
origin/main@6ed7b8d重测 —— 数字现在是对的,而这恰恰证明卡片的论点跑卡片自己给的命令:
$ for f in src/objects/*.object.ts; do grep -c "Field.lookup('sys_user'" "$f"; done | paste -sd+ | bc 15 src/objects/event_attendee.object.ts:257 「HotCRM holds 15 lookups on `sys_user`; the other 14 …」 test/event-attendee-cascade.test.ts:70 同一句两处都写 15,真实值也是 15 —— 今天完全一致。
⚠️ 而这正是卡片预言的状态,一字不差:PR for #1181 removes
crm_account.renewal_owner, which brings the real count to 15 and makes both sentences accurate again — by coincidence, not because anything now holds them there.⇒ 前提成立,且成立的方式比卡片写的时候更有说服力:这个数字在无人看管的情况下先漂到 16、又漂回 15。记的是缺守卫,不是当前值 —— 而当前值碰巧正确,正是这类缺陷最难被发现的形态。
裁定:走第二条路(去掉整数,断言定性主张)
卡片列了两条且不给推荐。本席裁第二条:
-
✅ 删掉两句里的具体整数,保留定性主张(「every other
sys_userlookup isset_null」),并加一个直接断言它的测试。 -
⛔ 不要走第一条(从构建产物推导计数并断言注释里的数字)。理由是轴③:那样做等于新增一份需要维护的数字,只是给它加了把锁。而真正承重的论据从来不是「15」这个数 —— 卡片自己说得很清楚:
it is the evidence for "a deleted user's references degrade is already this app's stance", which is why
crm_event_attendee.sys_userusescascaderather thanrestrict.支撑这个立场的是**「其余每一个都是
set_null」**,不是「一共有 15 个」。断言定性主张既更强(它直接钉住论据本身),又零维护 —— 新增一个sys_userlookup 时不需要有人去改注释。
⇒ 一个 PR:两处散文改写 + 一个断言「所有非
crm_event_attendee.sys_user的sys_userlookup 的onDelete都是set_null」的测试。⚠️ 反验要求新断言必须先证明会红:临时把某个
owner_id的onDelete改成别的值,看它变红,再还原。⛔ 「加了断言、全绿」不是验收证据 —— 一个把整数换成定性主张却写成永真式的测试,比原来那句注释更糟,因为它看起来被守着。⚠️ 还原时用git checkout HEAD -- <路径>(裸形式读的是 index,可能带着变异),并在磁盘上核验还原结果,⛔ 不看退出码。本仓已为这个陷阱付过账。面:
src/objects/event_attendee.object.ts的注释 +test/event-attendee-cascade.test.ts的文件头与新断言。同族:#1282(
forecast-seeds.test.ts里「eight authored records」而实际七条 —— 同样是散文里手工维护的计数,同样无守卫,本轮同批立卡)。两张卡可考虑同一 dev 连做,但文件面不相交,⛔ 不折叠。
Generated by Claude Code
-
- addedpm:dispatchedDispatched to a dev agent by /pm-dispatchDispatched to a dev agent by /pm-dispatchand removedpm:queueReady for the PM dispatch loopReady for the PM dispatch loop
on Aug 26, 2026 派发认领(R5)—
pm:queue→pm:dispatched- Session:
dea4cde2-db24-5125-950e-e38371290748 - Branch:
claude/issue-1188-sys-user-lookup-count-prose
裁定:卡片列了两条可能形状,本席裁第二条 —— 删掉整数,保留定性主张,⛔ 不要加一道去数它的守卫。(#1282 同族、同裁定,本轮并行。)
前提复核(
origin/main@cd198f10,本席实测)两句散文都还在,逐字:
src/objects/event_attendee.object.ts:257 // degrade". HotCRM holds 15 lookups on `sys_user`; the other 14 (every // `owner_id`, plus `product_manager`) are `set_null` test/event-attendee-cascade.test.ts:70 * HotCRM holds 15 lookups on `sys_user`; the other 14 — every `owner_id`, * plus `crm_product.product_manager` — are `set_null`⇒ 每句两个整数(15 和 14),共两个文件、四个整数。
⚠️ 今天这个数字是对的 —— 这不改变裁定,请不要因此认为无事可做$ for f in $(git ls-tree -r --name-only origin/main src/objects | grep '\.object\.ts$'); do git show origin/main:$f | grep -c "Field.lookup('sys_user'"; done | paste -sd+ | bc 1515 个 object 各一处,合计 15;控制词
Field.lookup(全域 57 命中 ⇒ 搜索确实够到了代码,15 不是空扫的产物。卡片自己已经说明了这一点:#1181 移除
crm_account.renewal_owner把真实值带回 15,是巧合,不是因为有什么东西把它按在那里。⇒ 本卡记录的缺口是缺生产者,不是当前值错。⚠️ 一个今天恰好正确的手维护数字,明天照样静默漂移 —— 上一次它漂到 16 也没有任何东西报警。改法
把两句里的
15和14都去掉,保留定性主张。例如:"A deleted user's references degrade" is already this app's stance. Every other
sys_userlookup in HotCRM — everyowner_id, pluscrm_product.product_manager— isset_null, and NO validation rule reads any of them …论证承重的是**「其余每一处都是
set_null」**这个全称命题,它不依赖计数;删掉整数后论证完整且更强(全称比「14 个」更难被下一次新增字段推翻)。⛔ 不要加一道从产物推导计数、再断言散文里那个数字的守卫。那是新增一份要维护的数字、只是给它加了把锁;轴③反对:作者改那个整数不会改变任何用户看到的东西,而守卫只是把维护成本从「静默漂移」换成「每次加字段就变红」。
⛔ 也不要顺手改这两段散文里的其他论证(
/api/v1/auth/delete-user那条路径链、attendee_resolves/attendee_type_exclusive那两条规则)—— 它们与本卡无关,且本席未复核它们。围栏(枚举)
✅ 你的面,仅此 2 个文件:
src/objects/event_attendee.object.ts(~257 行那句)、test/event-attendee-cascade.test.ts(~70 行那句)。只改散文,⛔ 一行代码不动、一条断言不动。⛔ 不得动:
test/forecast-seeds.test.ts——forecast-seeds.test.tssays "these eight authored records" where the seed holds seven — in the one file whose job is to state the seed's invariants exactly #1282 本轮并行(同族、同修法,但⛔ 不得折叠成一次交付)src/views/**、src/apps/crm.app.ts、test/{view-references,account-renewal-model,decorative-field-sweep,case-assignment,docs-search-navigation-views,view-tab-label-inert}.test.ts—— The wholelist.tabs[]entry is inert, not justlabel— 36 of 48 authored icons name something the console cannot render, and three test comments teach the wrong model #1307 本轮并行scripts/check-source-hygiene.mjs、playwright.config.ts—— The three root.tsfiles are outside the TODO/FIXME and copyright-header checks, andplaywright.config.tshas no header #1236 本轮并行content/docs/releases/**—— 任何代码 PR 恒禁
交付
worktree → 分支 → 改 →
pnpm test全绿 → changeset(本仓changeset-check.yml门住每个 PR,判据是本 PR 新增的.changeset/*.md;本卡只改注释、不发布任何东西,可用空 frontmatter 的 changeset或skip-changeset标签,二选一并在 PR 里说明)→ push → draft PR。⛔ 你的 seat 对
api.github.com是 403 —— 场外发现结构化回报给我,不要自己立卡。
Generated by Claude Code
- Session:
复核通过 → 入队(PR #1308)
对着 GitHub 的 diff 复核,不看报告。9/9 check 全绿(
Build and Test (22.x)逐名确认),draft 翻 ready,enable_pr_auto_merge SQUASH。围栏核对:零越界
判据 实测 改动文件 3 = 2 个围栏内文件 + 1 份 changeset ✅ 删除行 4,全是 ///*注释 ✅新增行 32 = 4 行注释 + 28 行 changeset ✅ 代码 / 断言 / deleteBehavior零改动 ✅ 被围栏排除的周边论证 /api/v1/auth/delete-user→dataEngine.delete(...)链、attendee_resolves/attendee_type_exclusive主张 —— 逐字未动 ✅并行卡的文件 forecast-seeds.test.ts/src/views/**/check-source-hygiene.mjs全未触碰 ✅changeset 空 frontmatter, Check Changeset→ success ✅⭐ dev 补上了本席派发词里缺的那一环
派发词让它把整数换成全称句,但没有说全称句凭什么成立。dev 自己发现了:那 14 个 lookup 一个都没有声明
deleteBehavior—— 全称主张实际靠的是 spec 的默认值。它没有假定,而是去已安装的@objectstack/spec@17.1.0src/data/field.zod.ts:906读了出来:deleteBehavior: z.enum(['set_null', 'cascade', 'restrict']).optional().default('set_null')
⇒ 「EVERY other
sys_userlookup isset_null」这句话之所以能写,是因为默认值是set_null,而这件事两条注释里原本一个字都没提。dev 把这份证据写进了 PR 正文,下一个人不必重新推导。这正是本席想要的读法:不是执行指令,是把指令依赖但没说出口的前提找出来并测掉。
三条场外发现,已代立卡(dev 的 seat 403,不能自立)
- A third hand-maintained integer in prose —
sharing-coverage.test.tssays "the other 14 zh-Hans doc pages" where 21 use the word, and 0 use the spelling it contrasts against #1310 ——sharing-coverage.test.ts:581的「the other 14 zh-Hans doc pages」。本席独立复测:控制词 67 个.zh-Hans.mdx页,含「营销活动」的 21 个,含 pre-zh-Hans 文档里 crm_campaign 有两个译名:administration 两页写「市场活动」,语言包与其余 14 个文件写「营销活动」 #830 的「市场活动」的 0 个。⇒ 该数字已经错了 7,且文件内部没有任何东西与它打架 —— 比本卡的整数更危险(本卡那个今天恰好是对的)。 - The 70% advisory band's first real output:
es-ES.ts(75.3%) andja-JP.ts(73.4%) are the only two files it names, and a third sits 224 bytes below it #1311 ——pnpm hygiene的咨询带点名es-ES.ts75.3% /ja-JP.ts73.4%。本席复测了全部被扫文件:这两个是仅有的两个越过 70% 带的文件,而第三名flow-scheduled.test.ts距带只差 224 字节。这是 R4 那条咨询带(The 100KB hygiene cap has no early warning: silent at 99%, red at 101% — three files have now been found at the moment it bit #1287 / PR ci(hygiene): warn at 70% of the 100KB cap instead of only at 101% (#1287) #1299)第一次真正开火,也回过头证明了当时选 70%(而非卡片建议的 90%)是对的 —— 90% 今天照样一个都点不到。 flow-scheduled.test.tsopens with "All six scheduled flows" — there are nine, and this very file imports and tests all nine #1312 —— 由forecast-seeds.test.tssays "these eight authored records" where the seed holds seven — in the one file whose job is to state the seed's invariants exactly #1282 的 dev 报出的第四位同族成员,见该卡。
本卡待 PR 合入
main后由本席在移动后的 ref 上复验并关闭。
Generated by Claude Code
- A third hand-maintained integer in prose —
- removedpm:dispatchedDispatched to a dev agent by /pm-dispatchDispatched to a dev agent by /pm-dispatch
on Aug 26, 2026 已落地并在移动后的
mainref 上复验 → closedcompleted⛔ 不从合并调用的返回值判定,照例 fetch 后读树。
main @ 96770774 docs(event-attendee): state the sys_user cascade rationale as a universal, not a count (#1308) "15 lookups" in src+test : 0 (want 0) "the other 14 " in the two fenced files : 0 (want 0) src/objects/event_attendee.object.ts:257 : // degrade". EVERY other `sys_user` lookup in HotCRM (every `owner_id`, test/event-attendee-cascade.test.ts:70 : * EVERY other `sys_user` lookup in HotCRM — every `owner_id`, plus 控制读数(证明文件没有被删或掏空): event-attendee-cascade.test.ts : 490 行两个整数全数消失,两句全称主张各自就位,文件完好。
Generated by Claude Code
Observation
Two places state a counted figure about the app in prose, and both are maintained by hand:
src/objects/event_attendee.object.ts— "HotCRM holds 15 lookups onsys_user; the other 14 (everyowner_id, plus …) areset_null"test/event-attendee-cascade.test.ts— the same sentence in the file header.The figure is load-bearing for the argument it appears in: it is the evidence for "a deleted user's references degrade is already this app's stance", which is why
crm_event_attendee.sys_userusescascaderather thanrestrict. That reasoning stays sound, but the number backing it is not checked by anything.Measured on
main@ 2342811, before #1181:The comments said 15. The likely drift is
src/objects/article_feedback.object.tsgaining anowner_idafter the sentence was written.Why it is worth a card
test/docs-drift.test.tsalready pins the figures indocs/STATUS.mdagainst the built stack — it went red during #1181 the moment the field count changed, exactly as designed. Prose figures insidesrc/andtest/have no such guard, so they drift silently, and a stale count is read as a measurement by the next person deciding a referential-action question.Note on current state
PR for #1181 removes
crm_account.renewal_owner, which brings the real count to 15 and makes both sentences accurate again — by coincidence, not because anything now holds them there. The gap this card records is the missing guard, not the current value.Possible shapes (for triage, not a recommendation)
test/event-attendee-cascade.test.tsto derive the count from the built stack and assert the comment's number, the waydocs-driftdoes forSTATUS.md.sys_userlookup isset_null"), which a test can assert directly without a number to maintain.Found while implementing #1181; not fixed there to keep that diff scoped to the two renewal fields.