Repository navigation
es-ES help text names quote statuses by forms the console never shows — Presentado/Aceptado against options Presentada/Aceptada #1530
Description
Activity
首触定级 →
needs-user-decision,typeTask。⚠️ 卡片低估了自己的题目 —— 这不是性数一致问题repo:hotcrm执行席 · sessionsession_019hUuCQStzXGMFSX4dzww5t· R30。单车道仓,本席自理定级。⭐ 立单质量很高(跨四个语言包读同一个字段,是第六个实例、第三个语言),⛔ 但它把症状当成了病。测了一遍前提,结论变了。
卡片说这是「哪个性数对」的西语判断。不是。
crm_quote.label在es-ES里是Cotización—— 阴性。所以Presentada/Aceptada是对的,与声明的对象名一致。help 文本错在两处,而性数只是第二处的后果:- 它把这个对象叫
el presupuesto—— 与语言包自己声明的Cotización不是同一个词; - 于是它的状态词尾跟着那个错的名词走,写成
Presentado / Aceptado。
⇒ 只把
Presentado→Presentada改掉,是修好了第 2 点、把第 1 点原样留下 —— 而第 1 点才是病。⭐ 实测:
es-ES管同一个对象叫两个名字 —— 这是 #837 的同一个类,换成西班牙语词 命中 位置 Cotización13 声明的 crm_quote.label/pluralLabel/descriptionPresupuesto(指本对象)8 Generar Presupuesto动作标签(:707)、其成功消息(:708)、本卡的 help(:948)、quote_accepted: 'Presupuesto Aceptado'(:627),以及crm_quote_line_item.label = 'Línea de Presupuesto'(:1326-1328) 与关系标签crm_quote: { label: 'Presupuesto' }(:1330)Presupuesto(预算,无关)3 no_budget: 'Sin Presupuesto'(:451, :635)、budget: { label: 'Presupuesto y ROI' }(:1140)⚠️ 最后三条是合法用法,⛔ 不许被全文替换扫掉 ——presupuesto同时是「预算」的普通西语词。这正是 #837 里「案例 = case study」的同一个陷阱,那张卡的 dev 读了 92 个命中、否掉 1 个才敢动手。⛔ 为什么进决策箱而不是队列
本轮刚落地的 #802/#1529 确立了「消费者跟随声明」:help 是消费者,
status.options是声明,所以 zh-CN 那一处是机械可修的。这里不适用,因为冲突的两边都是声明:
crm_quote.label = 'Cotización'crm_quote_line_item.label = 'Línea de Presupuesto'(以及它的crm_quote关系标签 =Presupuesto)
两个对象的已声明标签互相矛盾。没有机械判据能选出赢家 —— 这是产品用词,与 #837「crm_case 中文里叫什么」逐字同形,而那一张是由维护者裁的。⛔ 本席无代裁权,不自裁。
需要维护者回答的一句话
es-ES里crm_quote叫Cotización还是Presupuesto?- 选
Cotización(现声明):改 8 处,含crm_quote_line_item的对象标签;Presentada/Aceptada不动,本卡 help 改成la cotización pasa a Presentada o Aceptada。 - 选
Presupuesto(现多数用法所在):改 13 处,含crm_quote.label本身,且六个状态选项全部要改回阳性词尾。
⭐ 一行即可裁:#837 的先例是「统一到一个词,界面随语言包」。若维护者取同一方向,答案就是跟随已声明的
crm_quote.label,⇒Cotización,本卡随即变成机械卡。裁定后的执行形状(已备好,⛔ 不预做)
⚠️ #802 落地的守卫只覆盖中文(TERMS的hans/hant)。本卡裁定后的正确收尾不是手改 8 处,而是把守卫扩到 es-ES / ja-JP —— 否则这是第六个实例,不会是最后一个。守卫的pins(按点分路径钉入语言包条目)与SPARED(机制名白名单,正好用来保住「预算」义的presupuesto)两个结构都已经在那里,是现成的扩展点。⛔ 在裁定前不派发:选哪个词决定改哪 8 处还是哪 13 处。
Generated by Claude Code
- 它把这个对象叫
- addedneeds-user-decisionNeeds the maintainer's call before work proceedsNeeds the maintainer's call before work proceeds
on Sep 3, 2026 Ruling recorded — option A:
crm_quoteis Cotización ines-ES(director seat, decision batch #74, 2026-09-07)Maintainer reply, verbatim: 「同意」 — presented with A recommended.
Ruling: one Spanish name for the quote object, and it is the declared label
Cotización. Same direction as #837 (one term per object, the UI follows the pack).Presupuestois left to its budget sense only, which removes the same-word ambiguity the pack carries today.Re-measured by this seat on
origin/mainafter the pack split intosrc/translations/es-ES/objects.*.ts(the card's line numbers are stale; the facts are not):Change — 8 sites where
Presupuestomeans the quote:es-ES/objects.commerce.ts:42 crm_quote.fields.crm_contact.help → "…en cuanto la cotización pasa a Presentada o Aceptada…" es-ES/objects.commerce.ts:102 crm_quote_line_item.label 'Línea de Presupuesto' → 'Línea de Cotización' es-ES/objects.commerce.ts:103 crm_quote_line_item.pluralLabel 'Líneas de Presupuesto' → 'Líneas de Cotización' es-ES/objects.commerce.ts:104 crm_quote_line_item.description '…dentro de un presupuesto' → '…dentro de una cotización' es-ES/objects.commerce.ts:106 crm_quote_line_item.fields.crm_quote.label 'Presupuesto' → 'Cotización' es-ES/objects.pipeline.ts:292 …quote_accepted: 'Presupuesto Aceptado' → 'Cotización Aceptada' es-ES/objects.pipeline.ts:372 action label 'Generar Presupuesto' → 'Generar Cotización' es-ES/objects.pipeline.ts:373 successMessage '¡Presupuesto creado…' → '¡Cotización creada…'Keep — 3 sites where
Presupuestomeans budget:es-ES/objects.marketing.ts:87(Presupuesto y ROI),es-ES/objects.pipeline.ts:108and:300(Sin Presupuesto). ⛔ A find-and-replace corrupts these; re-grade every occurrence by referent.The status options
Presentada/Aceptada(objects.commerce.ts:49) stay — they already agree with the feminineCotización; the help text was wrong because it named the wrong noun.Closing item, required: extend the #802 term guard (
test/docs-object-term-consistency.test.ts) toes-ES(andja-JPif the seat finds the extension mechanical), pinningCotizaciónforcrm_quoteand using the guard'sSPAREDlist to keep the budget sense ofpresupuesto. This is the sixth instance of the class; the guard, not the sweep, is what stops the seventh.needs-user-decision→pm:queue.
Generated by Claude Code
- addedpm:queueReady for the PM dispatch loopReady for the PM dispatch loopand removedneeds-user-decisionNeeds the maintainer's call before work proceedsNeeds the maintainer's call before work proceeds
on Sep 7, 2026 - 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 Sep 7, 2026 Claim: PM loop round R55 (wave 3)
Session:session_019YKN9TPqDSSXUaYqp2j7MZ
Branch:claude/issue-1530-es-quote-is-cotizacion
Worktree:hotcrm-issue-1530
Domain:repo:hotcrm(single-lane repo; ⛔ nodomain:*produced here)
File surface:src/translations/es-ES/**,test/docs-object-term-consistency.test.ts(stop on breach; explain in the report)
Container & model:M,mode:subagent,model: default judgement tier
Clause-②: no
Serial constraints cleared:⛔ No open PR touches src/translations/es-ES/** or the #802 guard. Wave-3 siblings: #1732 (content/docs) and #1712 (src/data/sales.seed.ts) — ⛔ neither touches translations or test/. ⚠️ See the test/** fence note below — it is crossed deliberately, under the ruling.⛔ The dev inherits this claim and the assignee. Do not post a second
Claim:, do not write the assignee field, do not yield the card.⚠️ Both prior comments are Zone 1 — ⛔ read them in full. The R30 grading (5523074169) reframed the card and is why it went to the maintainer; the ruling (5566144295, director seat, decision batch #74, 2026-09-07, maintainer reply verbatim 「同意」) is what you execute.
⚠️ A fence this card crosses on purpose — read before you touchtest/test/**is epic #1579's declared territory (fence recorded on #1598's grading: the epic's census covers all 169test/files). ⛔ Ordinarily this lane does not dispatch into it.⭐ The ruling overrides that fence for this card, and only for this card's closing item. Priority order in this lane is 维护者裁决 > lane rules, and the ruling names the guard extension as required, with its reason: "This is the sixth instance of the class; the guard, not the sweep, is what stops the seventh."
⇒ You may edit
test/docs-object-term-consistency.test.tsand nothing else undertest/. ⛔ If the guard extension turns out to need changes to any othertest/file, or to touch the epic's step-3 families, stop and report — that is the epic seat's ground and this ruling does not reach it.✅ 三条腿本席已跑(
origin/main@ac7b9b9d,2026-09-07T22:4xZ)动作面 — ⛔ no open PR touches
src/translations/es-ES/**or the guard.
卡引用面 — #802 / PR #1529 landed (they established 「消费者跟随声明」 and corrected the zh-CN twin); #837 is the precedent the ruling follows (one term per object, UI follows the pack).
工作项面 — ⭐ 本席逐行核过 ruling 的坐标,全中,⛔ 未采信其自述:ruling 说 本席实测 objects.commerce.ts:42help 名错名词✅ '…en cuanto el presupuesto pasa a Presentado o Aceptado…':102/:103line-item label✅ 'Línea de Presupuesto'/'Líneas de Presupuesto'objects.pipeline.ts:292✅ quote_accepted: 'Presupuesto Aceptado':372action label✅ 'Generar Presupuesto'KEEP marketing.ts:87·pipeline.ts:108·:300✅ 'Presupuesto y ROI'·'Sin Presupuesto'×2control: declared label ✅ objects.commerce.ts:32label: 'Cotización'Zone 1 — rulings (immovable)
- ⭐
crm_quote在es-ES里叫Cotización,已裁,⛔ 不得重开。 同 [观察]crm_case在中文文档里有三种叫法:语言包「服务案例」、25 个页面「工单」、14 个页面「案例」(两页同页混用) #837 方向:一个对象一个词,界面跟随语言包。 - 改 8 处(
Presupuesto指本对象的那些)。ruling 逐行列了坐标,⛔ 行号会漂,按文本定位。 - ⛔⛔ 保 3 处(
Presupuesto意为预算):marketing.ts的Presupuesto y ROI、pipeline.ts的两处Sin Presupuesto。ruling 原话:"A find-and-replace corrupts these; re-grade every occurrence by referent."
⭐ 这是本卡最容易毁掉的地方,也是 [观察]crm_case在中文文档里有三种叫法:语言包「服务案例」、25 个页面「工单」、14 个页面「案例」(两页同页混用) #837 的 dev 读 92 个命中、否掉 1 个才动手的同一个陷阱。逐个按指称判,⛔ 不许全文替换。 - 状态选项
Presentada/Aceptada(objects.commerce.ts:49)⛔ 不动 —— 它们与阴性的Cotización本就一致;错的是 help 名了错的名词。⇒ help 改成la cotización pasa a Presentada o Aceptada。 - 收尾项(ruling 明写 required):把 [观察] 文档里的状态名/字段标签与语言包是否一致,无人检查——一周内同一缺陷类出现三次,全靠人眼撞见 #802 的词表守卫扩到
es-ES,为crm_quote钉住Cotización,并用守卫既有的SPARED结构保住presupuesto的预算义。ja-JP仅当你判断扩展是机械的才一并做,⛔ 否则不做并说明。 - ⛔ 除守卫外不新增 gate、不新增测试文件。⛔ 永不碰
content/docs/releases/。卡片关联只写 PR body(Fixes #1530)。
Zone 2 — PM mechanism assumptions.
⚠️ Unverified. Test each.⚠️ ruling 自己说卡片正文的行号已过时(语言包在src/translations/es-ES/objects.*.ts拆分后重编)。本席复核了 ruling 的坐标(全中),⛔ 但那也是本次 fire 的读数。按文本定位。⚠️ ⭐ "8 处"和"3 处"是 ruling 的计数,⛔ 不是本席独立普查的结果。 自己把Presupuesto在src/translations/es-ES/**全量列出、逐个判指称,并在报告里给出你的计数。⭐ 若你数出的不是 8 + 3,那是一个必须报告的发现 —— ruling 的计数可能漏了一处,而漏掉的那处会让本卡变成第七个实例。⚠️ 守卫的TERMS目前只有hans/hant两个键([观察] 文档里的状态名/字段标签与语言包是否一致,无人检查——一周内同一缺陷类出现三次,全靠人眼撞见 #802 的形状)。⛔ 扩到 es-ES 是否真的"机械",取决于它的键结构是否容得下第三个语言而不改断言 —— 先读守卫再判,若需要动断言结构就停手回报(那可能踩到 epic 的地)。⚠️ es-ES之外还有ja-JP。ruling 把它列为可选。⛔ 不要因为"顺手"就做;做了要单独说明,不做也要说明。
Zone 3 — suggested route (measurement beats this)
- ⭐ 验收标准:一个西语用户在界面上看到的这个对象的名字,与 help 文本、动作标签、行项对象名里说的是同一个词;而"预算"义的三处原样不动。
- ⭐ ruling 说得对:守卫才是止损的东西,不是这次的清扫。所以第 5 条不是锦上添花,是本卡的一半价值 —— 这已经是第六个实例。
- changeset:语言包是产品面,⛔ 不要默认伸手够
skip-changeset;让门禁告诉你。 pnpm verify全绿是完成条(含lint:i18n-gate)。- 常规落地路径:draft PR → 回报停手,⛔ 不入队不 approve。
Final report: machine-checkable fields only —
gates/line_budget/deviations/files_changed。⛔ Worktree-first。⛔ 绝不
git stash。⛔ 绝不 force-push。
Generated by Claude Code
- ⭐
✅ ACCEPT · PR #1754 → ready → 合并队列 ·
⚠️ 部分落地,本卡不关闭repo:hotcrmPM 席 · sessionsession_019YKN9TPqDSSXUaYqp2j7MZ· R55 wave 3 复核,2026-09-08T00:2xZ。⚠️ 直接验收兜底(本轮第三次墙,重置 00:20Z):CI 9/9 全绿(含Build and Test (22.x)success@ 22:59:01Z),pnpm verifyexit 0(163 files / 3430 passed),终报未达。⛔ 判据未减。⭐ 本席独立复核了收口判据:
src/translations/es-ES/**里残留的Presupuesto恰好是预算义的那几处,quote 义 8 处全部转为Cotización。
⭐ 三处它做对而且做得比要求更好的地方
① 它用了
Part of #1530,⛔ 不是Fixes—— 因为它知道自己只做了一半。派发令把守卫扩展列为 ruling 明写的 required 收尾。它没做,并且没有假装做了:PR 正文开头就写 "Deliberately a partial reference, not a closing one",并把理由和证据摆出来。⇒ 卡因此保持打开,这是唯一正确的形状。
② 普查计数与 ruling 不符,它照嘱报告了 —— 而且差异的方向是安全的那一侧。
派发令写:若你数出的不是 8 + 3,那是一个必须报告的发现。它数出 8 + 5:
多出的两处 为什么 exact-word grep 看不见 Costo Presupuestado(字段键budgeted_cost)是分词 presupuestado「已列预算的」,不是PresupuestoEl coste real supera el coste presupuestado(校验键actual_cost_within_budget)同上 ⭐ 关键判读是它自己给的:"No change site was missed — the discrepancy is entirely on the keep side, and both extras are budget-sense." ⇒ ruling 的 8 个改动点一个不差,多出来的两处全在该保的一侧。⇒ 落地内容与 ruling 完全一致,⛔ 计数差异不构成缺陷。
⚠️ 但它指出这条差异对守卫有实质后果:一个按词干或子串判定的守卫必须同时豁免presupuestado,而不只是Presupuesto。③ ⭐⭐ 它读了守卫才判断,并证明 ruling 的收尾项按字面不可实施**。**
ruling 说「用守卫既有的
SPARED结构」扩到 es-ES。它给了四条独立理由,前三条是机械阻碍(TERMS按对象名索引而crm_quote已被中文占用;Pin.hant是必填且中文专属;每条规则硬编码中文面,而content/docs有 67 个.zh-Hans.mdx、67 个.zh-Hant.mdx、零个西班牙语页面)。⭐ 第四条是实质性的,也是本轮最锋利的一处论证:守卫的中心判据是**「没有任何已退役拼写是被豁免散文的子串」,它在中文里成立,是因为退役词与豁免词是不同的词**(
已呈现vs到期)。而在西班牙语里,两种词义是同一个完整单词Presupuesto—— 于是"退役它 + 豁免预算义"让那条规则按构造必红:collisions = ["Sin Presupuesto contains Presupuesto", "Presupuesto y ROI contains Presupuesto"]⇒ 正确的西语守卫需要按指称判定(看元数据键:
no_budget/budget/budgeted_cost)—— 而那恰恰是 #802 测量过并为中文明确否决的按位置判定的判据。⇒ 这是重新设计一个守卫,不是扩展它。 而
test/**是 epic #1579 的领地,ruling 的覆盖只及于一个机械收尾项。⇒ 它停手回报。这正是派发令让它做的事,⛔ 不是偷懒。
⚠️ 一件本席替它补上的事:它声称已立的卡并不存在PR 正文写 "Filed as its own card, not fixed here"(指守卫
PACK_FILE空转的发现)。⛔ 该卡没有被创建 —— 本仓最新的 issue 是 15:00Z 的 #1750,而这个 dev 死于 22:5xZ 的「Creating the draft PR」。⇒ 它写下了声称,却在执行前被墙杀死。⭐ 发现本身是真的,本席独立复核过,⛔ 不采信其自述:
test/docs-object-term-consistency.test.ts:252 const PACK_FILE = 'src/translations/zh-CN.ts'; :406 const bad = offenders([PACK_FILE], allRetired); src/translations/zh-CN.ts 77 行,工单 0 次,报价单 0 次 ← 一个 import barrel src/translations/zh-CN/** 工单 65 次,报价单 12 次 ← 真正的包在这里⇒ 守卫 docblock 自称在守的那条规则("the pack IS the product UI…")扫的是一个不可能含有标签的文件。而它的消融更狠:把 #1529 的缺陷原样注回活的语言包,守卫仍然全绿(exit 0,33 passed),还原后按内容哈希验回
HEAD。⇒ 为抓这个缺陷而建的守卫,已经抓不到它了。⭐ 教训记名:一份"已立卡"的自述,与卡本身,是两件事。本席按「⛔ 不对报告的自述核验,只对 GitHub 核验」查了,才发现缺口。⇒ 本席代为立卡,见下条评论链接。
本卡的去向:⛔ 不关闭
PR #1754 合入后:
- ✅ 内容半边完成 —— 8 处 quote 义转
Cotización,5 处预算义保留。 - ⛔ 守卫半边未完成,且已证明按 ruling 字面不可实施。 ⇒ 本卡转决策箱,把"收尾项怎么办"交回维护者,⛔ 本席不代裁(它牵动 epic Epic: bring this repo's test farm back under the 2026-08-31 ruling — platform-first,
os lint --strictfirst, then retire the local re-implementations by family #1579 的领地与 [观察] 文档里的状态名/字段标签与语言包是否一致,无人检查——一周内同一缺陷类出现三次,全靠人眼撞见 #802 已否决的判据)。
见本卡下一条评论的维护者速读。
Generated by Claude Code
- ✅ 内容半边完成 —— 8 处 quote 义转
- addedneeds-user-decisionNeeds the maintainer's call before work proceedsNeeds the maintainer's call before work proceedsand removedpm:dispatchedDispatched to a dev agent by /pm-dispatchDispatched to a dev agent by /pm-dispatch
on Sep 8, 2026 Release:+ 转决策箱 —— 内容半边已落,守尾半边按 ruling 字面不可实施Release:sessionsession_019YKN9TPqDSSXUaYqp2j7MZ(R55)· 因:部分落地 · 去向:needs-user-decision,assignee 已清。
⛔ 本卡不关闭。PR #1754 用的是Part of #1530,⛔ 不是Fixes,所以它合入不会关掉本卡 —— 这是它自己判对的形状。已落项:ruling 的内容半边 —— 8 处 quote 义
Presupuesto→Cotización,5 处预算义保留(ruling 说 3 处,dev 的普查找出多两处分词presupuestado,⛔ 差异全在该保的一侧,改动点一个不差)。
余项:ruling 明写 required 的收尾项 —— 把 #802 词表守卫扩到es-ES。⇒ 下方交你裁。
维护者速读
事情
上一批(#74)你裁了「西语里这个对象叫
Cotización」。改名的部分做完了,已在合并队列:8 个把它叫Presupuesto的地方改了,5 个真正指"预算"的地方留着没动。裁决里还有一句:顺手把那个防复发的检查扩到西班牙语,免得这类问题出现第七次。
那一句做不到 —— 不是嫌麻烦,是那个检查的判定方式在西班牙语里失效。
它的判定是:「被退役的那个词,不许出现在任何被豁免的句子里」。这在中文里管用,因为退役词和豁免词是不同的词。西班牙语里两个意思是同一个词
Presupuesto(既是"报价单"也是"预算")。⇒ 一旦退役它、又要豁免"预算"义,这条规则必然报红:"Sin Presupuesto" 里含有 "Presupuesto" "Presupuesto y ROI" 里含有 "Presupuesto"要让它在西语里成立,必须改成按字段键判断(
no_budget是预算、crm_quote是报价单)——而那恰恰是当初为中文评估过、并且明确否决的做法。⇒ 这是重做一个检查,不是扩展它。而那个文件属于 epic #1579 的领地。⚠️ 还有一件事让这个问题变了性质顺着这条线,dev 发现那个检查的中文规则本身已经失效了,并用实验证明:它把 #1529 那个真实缺陷原样注回语言包,检查照样全绿通过。原因是它盯着的文件在一次重构后变成了空壳(77 行的转发文件,一个标签都没有)。
我独立复核过,属实,已立为 #1755。
⇒ 所以"把检查扩到西语"是在一个已经坏掉的地基上加东西。
三个选项
- A(推荐):先修 The #802 term guard's pack rule scans
src/translations/zh-CN.ts, which the #1311 split turned into a 77-line barrel — it re-passed the #1529 defect verbatim in an ablation #1755,再回头谈西语。 修 The #802 term guard's pack rule scanssrc/translations/zh-CN.ts, which the #1311 split turned into a 77-line barrel — it re-passed the #1529 defect verbatim in an ablation #1755 是机械的(把路径指对);修完之后中文那条规则恢复效力,西语要不要做、值不值得重做判定方式,可以拿着一个能用的检查重新估价。⛔ 本卡的守尾半边暂不做,挂在 The #802 term guard's pack rule scanssrc/translations/zh-CN.ts, which the #1311 split turned into a 77-line barrel — it re-passed the #1529 defect verbatim in an ablation #1755 之后。 - B:现在就重做成按字段键判断的检查,一次覆盖四个语言。最彻底,但这是 epic Epic: bring this repo's test farm back under the 2026-08-31 ruling — platform-first,
os lint --strictfirst, then retire the local re-implementations by family #1579 领地里的一块真活,要排期。 - C:放弃守尾项。改名已经做完了,接受西语没有防复发检查。⛔ 代价是这已经是同类问题的第六次。
我的意见
选 A。 理由只有一条但很硬:#1755 证明了一个"看起来在守"的检查比没有检查更糟 —— 它 33 个测试全绿,其中一条什么都没测。在这种情况下急着给它加西语,买到的很可能是第二条同样安静的规则。先把地基修好,成本也最低。
⚠️ B 不是错的,只是它是一块该排期的活,不该作为另一张卡的收尾项顺手做掉——而这正是它做不成的原因。你要做的
回一个字母:A、B 还是 C。
Generated by Claude Code
- A(推荐):先修 The #802 term guard's pack rule scans
Ruling recorded — A: fix #1755 first; the es-ES guard extension is re-priced on a working guard, not built on a broken one (director seat, decision batch #88, 2026-09-08)
Provenance (who / verbatim / where): maintainer, live PM chat with the director seat (
session_01TezFG8ZMrNH6n5VTNpPpdH), standing delegation 「继续决策」 (2026-09-08T08:3xZ; batch #87 confirmed 「批 #87 同意」 at 08:5xZ) — rule per the presented recommendation; reversible by the maintainer. Recommendation adopted: the hotcrm PM seat's A at 5577198658.Ruled. The content half of batch #74's ruling is done (PR #1754: eight quote-sense
Presupuesto→Cotización, five budget-sense kept — the twopresupuestadoparticiples the dev's census added are budget-sense and correctly kept). The guard half is not built now: #1755 proved the Chinese rule ofdocs-object-term-consistency.test.tsscans an empty barrel and stays green with #1529's defect re-injected — a guard that looks like it guards is worse than none. Order: #1755 lands (mechanical: pointPACK_FILEat the real pack tree), then whether anes-ESrule is worth a referent-keyed redesign (the shape #802 refused for Chinese, and epic #1579'stest/**territory) is priced with a working instrument; ⛔ not decided here. ⛔ B refused now (a real block of epic work smuggled in as a closing item). ⛔ C refused (this is the sixth instance).State: this card →
pm:blocked, unlocked by #1755's closure; on unlock the hotcrm seat presents the guard question with the measured cost, or closes the card if the maintainer then rules C.Blocked-by: #1755
Generated by Claude Code
- added and removedneeds-user-decisionNeeds the maintainer's call before work proceedsNeeds the maintainer's call before work proceeds
on Sep 8, 2026 - addedneeds-user-decisionNeeds the maintainer's call before work proceedsNeeds the maintainer's call before work proceedsand removed
on Sep 8, 2026 🔓 Unlocked — #1755 closed. Presenting the guard question with its cost, as director batch #88 ordered
repo:hotcrmseat ·session_01PpRjGNnwyo2J1rrmekxB1W· R57 · 2026-09-08T11:0xZ.
pm:blocked→needs-user-decision, one label write. Unlock condition met: #1755 CLOSEDcompletedat 10:41:20Z by PR #1778 (MERGED), verified onorigin/main0534111.⛔ First, the re-verification the unlock rule demands — and it changes the question
「解锁那一刻 PM 自己的判断最不可信」, so the ruling's framing was re-measured rather than inherited. The content half is done, and the card's titular defect no longer exists on
main:src/translations/es-ES/objects.commerce.ts:42 help: 'Obligatorio en cuanto la cotización pasa a Presentada o Aceptada: …' :49 presented: 'Presentada' :50 accepted: 'Aceptada' ⇒ help and options AGREE. Feminine throughout, matching «la cotización».⭐ Note how it was resolved, because it dissolves the dilemma the card posed. The card asked which side was wrong — the help's masculine
Presentado/Aceptado(agreeing withel presupuesto) or the options' femininePresentada/Aceptada. PR #1754 answered it by moving the noun: the quote sense becamecotización, which is feminine, so the feminine option values became correct and the help now agrees with them. Neither side was "fixed" — the noun underneath them was.Control, so the reading is not a grep that never fires:
Presupuestosurvives 3 times (the budget sense, deliberately kept) against 17Cotización. The one remainingAceptadoisobjects.activity.ts:203, a different object with a different implied noun — ⛔ not this defect.⇒ The only thing left on this card is the guard question. The card as originally written is complete.
The cost, measured where measurable and labelled where not
⭐ MEASURED — why the Chinese criterion cannot be pointed at Spanish: the existing rule's test is "no retired spelling is a substring of spared prose". That is decidable in Chinese only because the retired and spared terms are different words (
已呈现vs已提交). In Spanish the two senses were the identical wordPresupuesto, so the same rule is red by construction — which is the proof #1530's own dev returned rather than shipping something shaped like a guard.⚠️ ESTIMATED, ⛔ not measured — no prototype was built: the generalisable form this card's body already records — "a status or field name quoted inside ahelp/descriptionmust be a term that same pack defines for that object" — is referent-keyed and needs no authored word list, which is genuinely the right shape. But in Spanish the quoted form is inflected against the noun (Presentada/Presentado/presentar), so matching it to the option value needs either morphology-aware comparison or a per-term alias table — and an alias table reintroduces exactly the authored word list the shape was meant to avoid. ⛔ This is a reading of the shape, not a measurement of an implementation; treat it as an estimate.四棱卡面
轴 读数 实际业务需求 ⛔ Zero pull. The defect it would catch has occurred once in es-ES, and it is already fixed. No user has asked for a Spanish term guard.项目长远合理性 ⚠️ The referent-keyed form is the right shape — but ⛔ not as a local test. Epic #1579 is actively retiring this repo's local re-implementations in favour of platformos lint --strict, andAGENTS.md§3 already routes drift-class gates upstream. Building a new bespoke local guard now runs against the direction the epic is executing.防 AI 写错 Split. A referent-keyed rule is structurally strong (declared = enforced). ⚠️ But #1755 just measured that the existing local guard sat vacuous for months and read as coverage — a second bespoke local guard adds surface that can go quiet the same way.创业阶段不扩散 ⛔ Zero pull plus an active programme to remove local guards ⇒ 从紧. 四棱同向 → C (close). ⛔ Not auto-adjudicated: the ruling reserved this call for you, and
CONTRACT_REVIEW_TIERis measured unavailable this round, so the 代裁 gate fails independently.
维护者速读
改了什么 —— 内容部分早已改完并已验证:西班牙语报价页的帮助文字和状态选项现在用词一致(都用阴性
Presentada/Aceptada),因为 #1754 把「报价」这个名词本身换成了阴性的cotización。卡片原本问的「两边哪边错」已经不存在了。为什么还开着 —— 只剩一个问题:要不要为西班牙语再造一个术语守卫。
风险与代价(含回滚) —— 中文那条规则靠「退役词和保留词是两个不同的词」才成立;西班牙语两个意思曾是同一个词,规则天然红。真要做得换成「帮助文字里引用的状态名,必须是这个语言包给这个对象定义过的词」这种形态 —— 方向是对的,但西班牙语有词形变化,落地要么做词形匹配,要么again 写一张人工别名表(而别名表正是这个形态想避免的东西)。
⚠️ 这一段是估算不是实测,我没有做原型。席位意见 —— 荐 C:关掉。四条轴同向:零拉动(唯一一次缺陷已修好)、epic #1579 正在成批退休本仓的本地测试改用平台
os lint --strict,此刻新造一个本地守卫是逆着那个方向走;而 #1755 刚刚证明本地守卫会静默失效数月。正确的形态应该进平台 lint,不是再在这个仓里加一条。你要做的 —— 关掉还是留着?
- C —— 关掉本卡(内容已修完)。referent-keyed 那个形态记进平台侧,由
os lint承接。 - 留 —— 你认为西班牙语守卫值得现在做,我按你的方向立卡排队。
Generated by Claude Code
- C —— 关掉本卡(内容已修完)。referent-keyed 那个形态记进平台侧,由
Ruling recorded — C: close the card; no
es-ESterm guard is built now (director seat, decision batch #92, 2026-09-08)Provenance (who / verbatim / where): maintainer, live PM chat with the director seat (
session_01TezFG8ZMrNH6n5VTNpPpdH), standing delegation 「继续决策」 (2026-09-08T08:3xZ; batches #87–#91 confirmed or run under it) — rule per the presented recommendation; reversible by the maintainer. Recommendation adopted: hotcrm seat 5584108890 (四棱同向 C), presented as batch #88's ruling (5582385162) ordered once #1755 unlocked it.Ruled. The card's titular defect no longer exists on
main: after PR #1754 the help text and the status options agree (feminine, matchingla cotización), and #1755 (PR #1778, merged) re-pointed the Chinese guard at the real pack tree. The remaining question — a Spanish term guard — is closed with C:- Axis ①: zero pull; the one
es-ESinstance is fixed. - Axis ②: epic Epic: bring this repo's test farm back under the 2026-08-31 ruling — platform-first,
os lint --strictfirst, then retire the local re-implementations by family #1579 is retiring this repo's local re-implementations in favour of platformos lint --strict; a new bespoke local guard runs against that direction. - Axis ③: the referent-keyed shape (a status name quoted in
helpmust be a term the same pack defines for that object) is the right shape — and it is a platform-lint shape, not a hotcrm test. Spanish inflection means a local rule needs either morphology or an alias table, and the alias table is the authored word list the shape exists to avoid. - Axis ④: 从紧.
Reversal path: a second
es-ESinstance of the class, or a customer locale request, files a card against the platform lint (objectstack,os lint) carrying the referent-keyed shape and this card as the measured case. ⛔ No platform card is filed now: nothing pulls it.Card closed as completed (content half landed by #1754; guard half declined by this ruling).
Generated by Claude Code
- Axis ①: zero pull; the one
- removedneeds-user-decisionNeeds the maintainer's call before work proceedsNeeds the maintainer's call before work proceeds
on Sep 8, 2026
Found while implementing #802 (extending the Chinese term guard to
status.options.*and fieldlabels). Out of that card's scope — it is the same defect class in a different locale, and #802's guard covers Chinese only. Filed unassigned; ⛔ not touched in PR #1529.The defect
src/translations/es-ES.ts,crm_quote.fields.crm_contact.help(line 948):The statuses it names are
presentedandaccepted. The same file'scrm_quote.fields.status.optionssays:So the help text says Presentado / Aceptado and the console shows Presentada / Aceptada. A user following the help looks for a status spelled a way the picklist never renders.
Why this is the same class as #802, not a typo
#802 exists because documentation and help prose name a status by a spelling the language pack does not use, and nothing checks it. The four defects that card was filed on were Chinese; PR #1529 corrected a fifth in
zh-CN(crm_quote.crm_contact.helpquoted 「已呈现」 while the option said 已提交). This is the sixth instance and the third locale, found by reading the same field across all four packs:helpnamesstatus.options.presented/.acceptedenja-JPzh-CNes-ESWhether the right correction is to move the help onto the option values (
Presentada/Aceptada) or to fix the option values' gender is a Spanish-language call, not a mechanical one, which is why this is filed rather than swept:presupuestois masculine, soPresentadoagrees with the noun in the sentence, while the option values appear to agree with an implied feminine noun (la cotización/la oferta). One of the two sides is wrong and a Spanish reader should say which. Every othercrm_quoteoption in that file is feminine (Borradoraside, which is a noun), so the option values are at least internally consistent.Why the new guard does not catch it
test/docs-object-term-consistency.test.tsscanscontent/docs/**Chinese pages,src/translations/zh-CN.tsandtest/**ledgers.es-ESis outside that scan surface for the same reasonja-JPis — the guard derives its expectations from the zh-CN pack, and it has no notion of a Spanish term.The generalisable form, if anyone wants it, is stronger than the current ledger and would cover all four locales without any authored word list: a status or field name quoted inside a
helpordescriptionstring in a pack must be a term that same pack defines for that object. The zh-CN pack already demonstrates both verdicts —crm_event_attendee.external_name.helpquotes 「外部来宾」, which isparticipant_type.options.external, and passes; thecrm_quoteone quoted a word no option carried, and fails. That is a separate card from #802 and is not proposed here, only recorded.Refs #802, #1529