Repository navigation
docs(skills): objectstack-formula evals exercise label(record.kind), and refuse it in a predicate - #26810
Conversation
…and refuse it in a predicate Two eval cases join cel-predicates-formulas.json: a record name built from a select field expects label(record.kind) and refuses a hard-coded label ternary; a validation rule and a visibleWhen refuse label( where it faults. Four sentences that restated their own must_not_contain assertions are cut (212 bytes); the ratchet row rises to the measurement, 1046 -> 1352, under the ruling 「A:先削重复,余额按实测提高」. Claude-Session: https://claude.ai/code/session_01ADHkmPm7NR24Xypi61eyg8 Co-authored-by: Claude <noreply@anthropic.com>
席位核对ACCEPT ·
|
Contract reviewServed-tier: Director seat (summon #52, ledger objectstack#12708), summoned by the ① Derived judgments
② Semver level
③ Boundary flags
④ Design judgment
Implemented-by: VERDICT: PASS Generated by Claude Code |
Requested by Steve · project thread
Fixes #26760
Clause-②: no
Metadata-protocol: none
维护者速读
objectstack-formula技能的 eval 文件新增两例 —— 正例(用 select 字段拼记录名,须写label(record.kind),禁止硬编码标签的三元)、反例(校验规则与visibleWhen里禁止出现label(,它在谓词里会报错并中止写入);同文件删掉 4 句只是复述自身must_not_contain断言的话(212 字节),token 棘轮行按实测 1046 → 1352 上调,附一条@objectstack/skillspatch changeset。label(record.f),但没有任何 eval 检查 agent 真会用它,也没有 eval 拦住把它写进校验谓词(校验谓词不可求值 = 每次写入都失败)。skills/objectstack-formula/evals/cel-predicates-formulas.json(case 6、7 与 case 1/2/3/5 的删句),其次scripts/check-skills-token-ratchet.mjs的新行注释(算术),最后 changeset。node scripts/check-skills-token-ratchet.mjs,预期看到cel-predicates-formulas.json is 1352 tokens (ceiling 1352; headroom 0)与整体 ✓。skills/**为 Tier H,需 GOVERNED_APPROVERS 批准后由席位落地)。What changes
skills/objectstack-formula/evals/cel-predicates-formulas.json— two cases join the five:contract_versionrecords by version number and thekindselect so a zh-CN reader seesv2 · 清稿and an en-US readerv2 · Clean. Expected: atype: 'formula'nameFieldspelledF'v' + string(record.version_no) + ' · ' + label(record.kind)``;label()takes exactly `record.FIELD` of a select field, reads the option label in the reader's locale, `''` for null. `must_contain: ["label(record.kind)", "F`"]`; `must_not_contain: ["== 'clean' ?", "{record."]` — the hard-coded label ternary the card describes.contract_versionsave unlesskindis the clean copy, and showsigned_atonly oncestatusis signed. Expected: predicates over the STORED value — ascriptvalidationPrecord.kind != 'clean'(it fails when true) and `visibleWhen: P`record.status == 'signed'; thelabelmacro evaluates only in a formula field and faults in a validation,visibleWhenor hook predicate, aborting every write.must_contain: ["record.kind", "visibleWhen", "P"];must_not_contain: ["label(", "{record."]`.must_not_containassertions and are cut, 212 bytes = 53 units: case 1 "Field references are barerecord.FIELD, never brace-wrapped." (asserted by{record.), case 2 "Uses'draft'single quotes and barerecord.references." ({record.; the'draft'spelling stays in the expression), case 3 "NoISCHANGED()function." (ISCHANGED(), case 5 "Canonical property names only — neverconditionalRequired." (conditionalRequired:). Every other sentence carries a fact (why a guard is needed, what a shape stores, which gate refuses) and stays; every assertion stays.scripts/check-skills-token-ratchet.mjs— the file's row rises AT the measurement, 1046 → 1352, headroom 0, with the arithmetic in its comment under the standing ruling 「A:先削重复,余额按实测提高」: 1046 − 53 (the cut) = 993; + 1438 bytes = 359 units (the two cases) = 1352..changeset/26760-formula-label-eval.md—@objectstack/skillspatch (the package'sdistis built fromskills/**, so the bundle publishes).Behaviour the cases pin is read off
origin/main8b276385, not invented.packages/formula/src/stdlib.tsbindOptionLabel:labelis a macro taking exactlyrecord.FIELD;optionLabelOfanswers''for null and THROWS when the evaluation context carries nooptionLabels— which is what a validation, visibility or hook predicate's context is (only the data engine's formula-field reads pin the map, per the #26755 changeset), so the engine reports{ ok: false, kind: 'runtime' }and the write is aborted.packages/formula/src/option-label.test.tspins both ("refuses at run time when the context carries no option labels — never the stored value"; "compiles the one argument shape and refuses every other").content/docs/data-modeling/formulas.mdx§ "Record name from an option label" says the same for predicates: "fails loudly instead of comparing against a label; compare the stored value there".Readings (
skills/**touched)evals/cel-predicates-formulas.jsonlinesevals/cel-predicates-formulas.jsontokens (ceil(utf8 bytes / 4))skills/*/SKILL.mdlinesskills/*/SKILL.mdtokensNo
SKILL.mdmoves; the net addition is +306 units in one eval file, paid first by the 53-unit cut and then raised at the measurement.Tests
No runtime code changes. The eval file is read by no runner in this repository;
scripts/check-skills-token-ratchet.mjsis its only reader and is in the gate list below. JSON parses (JSON.parseover the file at head, 7 cases); everymust_containstring is absent from the same case'smust_not_containand present in itsexpected_output; in cases 6 and 7 nomust_not_containstring appears in theexpected_output.Acceptance notes
== 'clean' ?(the stored value the prompt names, compared and branched on); a ternary over another spelling would passmust_not_contain, and themust_containoflabel(record.kind)is what carries the teaching.labelmacro" rather thanlabel()so the ideal answer itself does not carry the string the case refuses (the same contradiction case 3 had onmain,ISCHANGED()inside its own refusal, is gone at this head: the paid-down cut removed that sentence).check:skill-docs/check:skill-refs/check:skill-examplesreadSKILL.md,references/and rule code fences, not eval JSON; the derived gate list below does not name them, consistent with that.Verification
Gate list derived at head with
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack(60 commands; the model tier line reads MANDATORY,skills/**clause ①, no one-line exit), each run with stdin closed, reconciled with--ran. Readings follow in the os-dev-report comment on the card.Generated by Claude Code