Repository navigation
.github/instructions/metadata.md teaches reference_to: (an unrecognized key — the spec prescribes reference) and an ObjectSchema import/export shape the repo never uses #1686
Description
Activity
首触定级 →
needs-user-decision,typeTask。⛔ 因为它的修法要动AGENTS.md本身repo:hotcrmPM 席 · sessionsession_018xtjdpZFjgWh4Ad9Wcx68J· R53。由 #1678 的 dev 立卡。为什么不是
pm:queue⭐ 不是因为证据不足 —— 证据是本轮最硬的之一(两条都带引擎逐字回执与全仓计数)。 是因为修哪一边是一个治理面的决定:
AGENTS.md: Cross-references viareference_to/lookup/masterDetailMUST use the prefixed name.⇒ 本仓的真相源文件自己写着一个
FieldSchema不承认的键。 简报只是忠实地照抄了它。⇒ 只修简报 = 让简报与
AGENTS.md打架;修AGENTS.md= 治理面变更,人工地板。⛔ 这不是 dev 能自裁的,也不是本席能自裁的。两条实测,本席采信(⛔ 未复核,如实标注)
①
reference_to不是FieldSchema上的键,规范提示的是reference。 引擎逐字回执:Unrecognized key(s) on this field: 'reference_to'. Did you mean 'reference_to' -> 'reference'? Until this shape was closed these were dropped silently — the field was still created, minus whatever the key was meant to constrain, protect or compute.⭐ 注意那句尾巴:这个形状被关掉之前,这类键是被静默丢弃的 —— 字段照建,少掉它本该施加的约束。这正是本仓反复在修的那一类失效。
全仓计数:reference_to在src/objects/*.object.ts里 0 次,18 个对象文件全部走Field.lookup(...)。②
@objectstack/spec根本不导出ObjectSchema,而简报教的是三处都错的形状:导入路径(该用/data)、构造方式(该用会 parse 的工厂ObjectSchema.create(...),而不是as强制转换 —— 那是给值加类型位置,根本不做检查)、导出方式(该用具名导出,src/objects/index.ts的 barrel 靠它自动注册)。⚠️ 本席只做了定级,没有重跑这两条。 ⛔ 派发前必须复验(见下)。呈报给维护者的两个问题(⛔ 本席不代裁)
AGENTS.md是否在同一笔 PR 里改成reference? 还是简报干脆不教裸键、改教Field.lookup(...)—— 树里唯一真实存在的形式?
⭐ 本席的输入(仅供参考):后者更强。裸键即使拼对了,也是在教一个手写、无校验的形状;而Field.lookup(...)是编译期就有类型的工厂,正是本仓 18 个对象文件的一致做法。⛔ 但AGENTS.md的那句话仍然是错的,该不该同笔修是维护者的事。- 定义示例的其余部分(导入路径、
.create()、具名导出)是否一并修? 还是另起一轮?
⚠️ 派发前置(裁决下来之后)- ⛔ 重跑那两条测量 —— 本席未复核,而本轮已经因为「转述未复核读数」出过事(test/authorization-coverage.test.ts: the lifecycle-bits guard now describes a platform state two minors stale #1634 的「17.2」)。
⚠️ .github/instructions/metadata.md与AGENTS.md都是治理面 ⇒ draft PR、⛔ 不入队、人工合并。⚠️ 与 PR docs(instructions): teach the logic brief the real ctx.api surface and the crm_ prefix #1685(.github/instructions/logic.md teachesbroker.find(name, { filters })and unprefixed object names — the exact example #855 already retired from AGENTS.md #1678)同文件 ——metadata.md刚被它改过(crm_前缀那一半),而该 PR 正在决策箱等维护者。⛔ 本卡必须串在 PR docs(instructions): teach the logic brief the real ctx.api surface and the crm_ prefix #1685 之后,否则两个改动会在人工地板上撞车。- ⛔ 守卫不扩(.github/instructions/logic.md teaches
broker.find(name, { filters })and unprefixed object names — the exact example #855 already retired from AGENTS.md #1678 已依 AGENTS.md:431 拒过一次)。⭐ 卡片自己点明了这个后果:「this one is caught by reading, not by a gate」—— 这是一个被接受的代价,不是待补的洞。
记名
⭐ 立单人在本席明确指示它修
reference_to: 'account'→'crm_account'之后,测出了这个键本身就不被承认,然后没有顺手改,而是立卡。⛔ 它当时若「顺手修对」,就等于在一个 brief-only 的 PR 里单方面推翻了AGENTS.md的一条规定。前缀那一半仍是净改进(错键+错名 → 错键+对名),两件事分得很干净。
Generated by Claude Code
- addeddocumentationImprovements or additions to documentationImprovements or additions to documentationneeds-user-decisionNeeds the maintainer's call before work proceedsNeeds the maintainer's call before work proceeds
on Sep 6, 2026 Ruling recorded — option A, both questions answered together (director seat, decision batch #74, 2026-09-07)
Maintainer reply, verbatim: 「同意」 — presented with A recommended.
Protocol-first:
@objectstack/specis the contract, and it has noreference_tokey (re-measured by this seat on objectstackorigin/main: zero occurrences underpackages/spec/src/data; the field key isreference;ObjectSchemais exported from@objectstack/spec/data, not the root). Both the brief andAGENTS.mdare consumers and align to it.Ruling:
- Q1 — the brief stops teaching a raw key at all.
.github/instructions/metadata.mdteachesField.lookup('crm_account', { label: 'Account' })— the only form the tree uses (18/18 object files, zero rawreference_to, re-measured). ⛔ It does not teachreference:as a hand-written key either; the factory is the taught form. AGENTS.mdis corrected in the same PR, all three sites::62and:284say "cross-references viareference_to/lookup/masterDetail" → say that lookup / master-detail targets (Field.lookup(...)/Field.masterDetail(...)) MUST use the prefixed name;:141's checklist item "Are allreference_topointing to real objects?" → "Do all lookup / master-detail targets name real objects?". ⛔ No otherAGENTS.mdsentence moves.- Q2 — the whole definition example is fixed in the same PR, not a second pass: import from
@objectstack/spec/data, construct withObjectSchema.create({...})(a parsing factory, not anascast), export a named const thesrc/objects/index.tsbarrel re-exports. One example, corrected once, matching the 18 real files. ⚠️ Serial after PR docs(instructions): teach the logic brief the real ctx.api surface and the crm_ prefix #1685 (.github/instructions/logic.md teachesbroker.find(name, { filters })and unprefixed object names — the exact example #855 already retired from AGENTS.md #1678'scrm_prefix fix in the same file, itself a governed draft awaiting the maintainer's merge). Branch frommainafter docs(instructions): teach the logic brief the real ctx.api surface and the crm_ prefix #1685 lands; ⛔ do not stack on its branch.- Both files are governed ⇒ draft PR, ⛔ not queued, maintainer merges. Re-run the two engine measurements in the PR body before editing (the triage seat declared it had not re-run them).
needs-user-decision→pm:queue.
Generated by Claude Code
- Q1 — the brief stops teaching a raw key at all.
- 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 Considered for dispatch at R57 and held — one blocker discharged, a new one in its place. Stays
pm:queue, unassigned.repo:hotcrmseat · sessionsession_01PpRjGNnwyo2J1rrmekxB1W. ⛔ No dev was started. No branch, no worktree, no claim. Recording both readings so the next attempt is cheap rather than premise-false.✅ The ruling's blocker #4 is discharged
⚠️ Serial after PR #1685 … Branch frommainafter #1685 lands; ⛔ do not stack on its branch.PR #1685 merged 2026-09-07T07:23:55Z (by the director seat, head
8faec05c). ⇒.github/instructions/metadata.mdis free of that constraint, and a branch cut from today'smainpicks up itscrm_prefix work as history rather than as a conflict.⛔ But the ruling's own item 2 collides with a card now in flight
Ruling item 2 requires
AGENTS.mdbe corrected in the same PR, at three sites (:62,:284,:141). And #1742 was dispatched this wave and is editingAGENTS.mdright now (branchclaude/issue-1742-agents-md-landing-posture).⇒ dispatching #1686 today would put two devs on the same hot file simultaneously — the exact serial violation the lane's hot-file rule exists to prevent, and one I would have walked into had I not read this card's comments before claiming it. ⛔ Held.
⚠️ Note the shape: the block is not that #1686 is unready. It is ruled, its measurements are named, and its prior serial constraint is gone. It is blocked only by a file it shares with a card that happens to be in flight. ⇒ it becomes dispatchable the moment #1742's PR lands, and it should be near the front of the order then.For whoever takes it — the ruling's pre-dispatch condition still stands
Re-run the two engine measurements in the PR body before editing (the triage seat declared it had not re-run them).
⛔ That is not discharged by anything above. The R53 grading explicitly marked both readings as taken on trust and not re-verified, and this lane has already paid once for relaying an unverified reading (#1634's "17.2"). The two to re-run at your own commit: that
reference_tois unrecognized byFieldSchema(the engine's own "Did you mean …reference?" receipt), and that@objectstack/specdoes not exportObjectSchemaat the root.⭐ Also still true and worth carrying:
AGENTS.mdis the file that taught the wrong key in the first place, so this card fixes the source and its downstream copy together. That is why the ruling refused to let the brief be corrected alone.Queue position behind it
AGENTS.mdis a hot file with four cards on it — #1742 (in flight), then #1745, #1620, #1618, plus this one'sAGENTS.mdhalf. ⛔ Serial, one at a time. PR #1746's merge freed the file this morning; it is now spoken for again.
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 Sep 9, 2026 zhuangjianguo commented
on Sep 9, 2026 CollaboratorMore actionsClaim: PM loop round R58
Session:session_017FzrA1G4U89KEMf7wfLmqq
Branch:claude/issue-1686-metadata-brief-lookup-factory
Worktree:hotcrm-issue-1686
Domain:repo:hotcrm(single-lane repo — ⛔ nodomain:*)
File surface:.github/instructions/metadata.md,AGENTS.md,.changeset/(stop on breach; explain in the report)
Container & model:M,mode:subagent,model: default judgement tier— ⛔dispatch-gates.mjs --tierREFUSES for this repo (noscripts/pm/here), so the tier is this seat's explicit decision, ⛔ not a tool reading
Clause-②: no
Thread-read: 5586637464
Serial constraints cleared:AGENTS.mdhot file — PR #1798 (#1742) MERGED 2026-09-08T15:25:38Z,origin/maintipf34efa3; PR #1685 (#1678) merged 2026-09-07 (8faec05c), discharging ruling item 4. #1745 · #1620 · #1618 are held serial behind this card and none is in flight. No other claim touches either file.Dispatched to a dev, who inherits this claim — ⛔ the dev posts no second claim and does not touch the assignee.
Both of the ruling's blockers are discharged — that is what changed
Batch #74 (
5566140153, maintainer 「同意」) is the standing ruling and is not reopened. R57 held this card (5586637464) for one reason only: ruling item 2 requiresAGENTS.mdbe corrected in the same PR, and #1742 was editing that file at the time. That card landed last night. Both named blockers are now gone and the card dispatches as ruled.⚠️ fold-or-serial — answered, ⛔ not defaultedFour queued cards share
AGENTS.md: this one, #1745, #1620, #1618. Fold gate ① (same defect shape, same fix — ⛔ not same file, not same subsystem) fails: a retired key spelling, a File Suffix Protocol inventory drift, a miscount plus an un-incremented ledger, and a rule-6 wording question are four different defects with four different fixes. ⇒ SERIAL, this card first (oldest, ruled, and the brief's designated first).⚠️ Reinforcing that answer with a measurement rather than a category: #1620's subject line isAGENTS.md:348, and:348is one of the three sites this card must edit. The two cards touch the same bullet. Serial is not a formality here.⚠️ A measured correction to the ruling — take the tree's reading, ⛔ not the ruling's line numbersRuling item 2 names sites
:62,:284,:141. Measured onorigin/mainf34efa3just now,reference_toinAGENTS.mdis at:62,:141,:348—:284no longer holds it; the file moved under #1603, #1746 and #1798. The count still balances at three, and the three sites map onto the ruling's three:ruling measured content :62:62"Cross-references via reference_to/lookup/masterDetailMUST use the prefixed name":284:348"All references — reference_to,lookup,masterDetail, cubesql, … — MUST use the prefixed form":141:141checklist: "Are all reference_topointing to real objects?"⛔ These line numbers are a lead, not a spec — locate by text at your own commit and re-derive the set yourself. If you find a fourth site, that is a finding: report it, do not silently widen. Control for the grep:
masterDetailreturns 3 lines inAGENTS.md, so a zero onreference_towould have been a broken search, not a clean file.Zone 1 — the ruling (⛔ not re-litigable)
- The brief stops teaching a raw key at all.
.github/instructions/metadata.mdteachesField.lookup('crm_account', { label: 'Account' })— the only form the tree uses. ⛔ It does not teachreference:as a hand-written key either; the factory is the taught form. AGENTS.mdis corrected in the same PR, all three sites: the two cross-reference sentences say that lookup / master-detail targets (Field.lookup(...)/Field.masterDetail(...)) MUST use the prefixed name; the checklist item becomes "Do all lookup / master-detail targets name real objects?". ⛔ No otherAGENTS.mdsentence moves —AGENTS.md:348counts the drift its own rule forbids as "four times", and the ledger at:353has not been incremented since #1620,AGENTS.mdFile Suffix Protocol is an inventory that drifted both ways: 4 of its 12 declared suffixes have zero instances insrc/, and 8 suffixes the app really authors are absent from it #1745 and AGENTS.md rule 6 says "UI nouns take the zh-CN pack wording", but a pack-carried noun that is not a list view must stay English — and only an ablation reveals it #1618 own their own sentences in this file and are queued behind you.- The whole definition example is fixed in this PR, not a second pass: import from
@objectstack/spec/data, construct withObjectSchema.create({...})(a parsing factory, ⛔ not anascast), export a named const thesrc/objects/index.tsbarrel re-exports. - Both files are governed ⇒ draft PR, ⛔ never queued, ⛔ never auto-merged, the maintainer merges. This is now written down in
AGENTS.md:578 §How a green PR lands— the rule PR docs(agents): state how a green PR lands, and the governed-surface exception #1798 landed. Your PR is governed under the rule it sits next to. - ⛔ The guard is not extended (
AGENTS.md:431, refused once on .github/instructions/logic.md teachesbroker.find(name, { filters })and unprefixed object names — the exact example #855 already retired from AGENTS.md #1678 and again on Orphaned locale keys are invisible to every i18n check — the gate only looks surface→translation #1262). The card names the consequence itself — "caught by reading, not by a gate" — and that is an accepted cost, ⛔ not a hole to fill. A PR that adds a gate here is out of scope.
Zone 2 — PM mechanism assumptions (
⚠️ must be tested; falsifying one is the highest-value thing you can return)- ⛔ Re-run both engine measurements at your own commit before editing any prose. This is the ruling's own pre-dispatch condition and it is not discharged: the R53 grading declared both readings taken on trust and not re-verified, and this lane has already shipped one wrong relayed reading (test/authorization-coverage.test.ts: the lifecycle-bits guard now describes a platform state two minors stale #1634's "17.2"). The two: that
reference_tois unrecognized byFieldSchema(capture the engine's own "Did you mean …reference?" receipt verbatim), and that@objectstack/specdoes not exportObjectSchemaat the root while@objectstack/spec/datadoes. Put both receipts in the PR body. - I assume the corrected example should mirror a real file in the tree rather than be written fresh. Check that claim: read an actual
src/objects/*.object.tsand make the example agree with it. If the 18 files are not in fact uniform, say so — the ruling's "18/18" is a re-measured figure but it is not mine, and I have not re-run it. - I assume
:141's checklist item is the only checklist entry naming this key. Verify; a second one is a fourth site.
Zone 3 — suggested route (⛔ optional, measurement beats it)
Fix
AGENTS.mdfirst, then the brief, so the brief is derived from a file that is already correct — the card's own argument for why the brief could not be fixed alone. If a different order reads better in the diff, take it and say why.Report
Terminal report to this issue first, then as the return message. Machine-checkable fields only —
gates/line_budget/deviations/files_changed. ⛔ Do not restate the PR body as narrative.⚠️ A declared deviation is a question for the seat; an undeclared one is a decision taken on the seat's behalf. Two R57 devs deviated from an explicit instruction and were right, both times because they said so in the first paragraph. If the ruling turns out to be wrong about something you can measure, stop and report the fork — ⛔ do not force the ruling through, and ⛔ do not quietly fall back to the other option.
Generated by Claude Code
- The brief stops teaching a raw key at all.
- added 5 commits that reference this issue
on Sep 9, 2026 os-dev-report
{ "issue": 1686, "status": "done", "branch": "claude/issue-1686-metadata-brief-lookup-factory", "pr": "https://github.com/objectstack-ai/hotcrm/pull/1809", "premise_still_valid": true, "summary": "Ruled scope delivered in full. AGENTS.md stops naming the retired `reference_to` key at all three sites; the brief teaches Field.lookup('crm_account', {...}) and the real definition shape (/data import, ObjectSchema.create(...) parsing factory, named export the src/objects/index.ts barrel re-exports). Both engine measurements re-run at my own commit before any prose was edited. Two same-class defects in the same brief were found by measurement and fixed as DECLARED deviations, each isolated in its own droppable commit.", "gates": { "chain": "pnpm verify = validate, typecheck, lint, lint:i18n-gate, hygiene, hygiene:tokens, build, test", "narrowed": false, "deferred_to_ci": null, "run_at_commit": "10bb230", "results": { "pnpm validate": 0, "pnpm typecheck": 0, "pnpm lint": 0, "pnpm lint:i18n-gate": 0, "pnpm hygiene": 0, "pnpm hygiene:tokens": 0, "pnpm build + pnpm test": 0 }, "verdict_line": "os-verify-lock: VERDICT command-exit 0 - held the lock 144s", "test_totals": "165 test files passed; 3453 passed, 1 skipped (3454)", "exit_code_discipline": "each exit captured into a variable before any pipe; heavy pair run under the shared verify lock with OS_VERIFY_LOCK_SLOT set" }, "line_budget": { "source_token_ratchet": "clean, and unchanged BY CONSTRUCTION - it measures src/**/*.ts and this diff touches no file under src/", "business_semantics_tokens": 84609, "interaction_layer_tokens": 37837, "authored_total_tokens": 137092, "doc_line_delta": "AGENTS.md +3/-3 (3 sentences, no others); .github/instructions/metadata.md +21/-16; .changeset/ +1 new file", "net_diff": "3 files changed" }, "deviations": [ { "id": "D0-line-numbers", "kind": "measured correction, no fork", "what": "Ruling item 2 names AGENTS.md sites :62, :284, :141. Re-derived by text at my commit the set is :62, :141, :348 - as the dispatch predicted. Count still balances at 3; no fourth site in this file.", "control": "masterDetail returns 3 lines in AGENTS.md, so the post-edit zero on reference_to is a real zero, not a broken search.", "action": "used the tree's reading" }, { "id": "D1-enable-search", "kind": "DECLARED DEVIATION - forced by the ruled change", "commit": "a679c3c", "what": "enable.search is not a key; enable.searchable is. Fixed as an intent-preserving rename.", "why_forced": "The ruling swaps an `as` cast (checks nothing) for ObjectSchema.create(...) (parses). Under the cast enable.search was inert; under the factory the brief's lead example THROWS. Shipping the three named edits and stopping would have published a brief whose flagship example fails on first use - the exact defect class this card removes, newly made load-bearing by the card's own fix.", "receipt": "Unrecognized key(s) on `enable`: `search`. ... `enable` is a closed vocabulary in which every flag carries an enforcement contract.", "vocabulary_probe": "accepted: trackHistory apiEnabled activities searchable files apiMethods | rejected: search notes tasks events fullTextSearch", "note": "engine offers NO did-you-mean for this one, unlike reference_to - caught only by running the parse", "reversible": "drop commit a679c3c; ruled work stands without it, but the example then throws" }, { "id": "D2-formula-field", "kind": "DECLARED DEVIATION - same class, NOT forced", "commit": "3b12fb6", "what": "Field example 4 taught `formula:` and `return_type:`, both rejected. Now teaches Field.formula({label, expression}).", "trap": "Following the engine's own fix-up hint to returnType: 'currency' STILL fails - the enum is number|text|boolean|date; currency is a field TYPE, not a formula return type.", "not_governance": "AGENTS.md names neither return_type nor returnType (zero occurrences; its single `formula` hit at :525 is the product's formula builder), so nothing ruled is touched.", "tree_answer": "quote_line_item and opportunity_line_item write this exact field as Field.formula({label, expression}) and omit returnType; 19 Field.formula calls in src/objects, exactly 1 returnType in all of src/", "reversible": "drop commit 3b12fb6; fully independent of D1 and of the ruled work" }, { "id": "D3-pr-footer", "kind": "platform artifact, no action", "what": "PR body carries two attribution footers: create appended the session-URL form, the later edit appended the bare form. Different strings, so the platform did not dedupe. Not re-patched - removing it would loop." } ], "files_changed": [ "AGENTS.md (3 sentences: :62, :141, :348)", ".github/instructions/metadata.md", ".changeset/metadata-brief-teaches-the-lookup-factory.md (new, empty frontmatter)" ], "tests": "M1 reference_to, re-run at my commit vs pinned @objectstack/spec 17.3.0: FieldSchema.safeParse rejects with unrecognized_keys and the verbatim receipt 'Did you mean `reference_to` → `reference`?'. NOTE the card and the R53 grading both transcribe that arrow as ASCII; the engine emits a Unicode arrow. Positive control: the canonical `reference` key parses clean, so the rejection is about the key, not the fixture. M2 root export: 'ObjectSchema' in require('@objectstack/spec') is false; /data gives function + function. A runtime `in` check cannot see type-only exports and the brief used the name in a TYPE position, so tsc was run on the brief's own two lines and is the decisive witness: error TS2305 Module '@objectstack/spec' has no exported member 'ObjectSchema' (exit 1). The ruled replacement type-checks clean (exit 0). SHIPPED-ARTIFACT PROOF (not intent): the two typescript blocks were extracted FROM the committed file, spliced, then (a) tsc --noEmit --strict exit 0 and (b) ObjectSchema.create() accepted them at runtime, emitting reference:'crm_account', a CEL expression, and searchable:true. All four shapes this PR touches were REJECTED at the parent commit and are ACCEPTED now - a real before/after reversal, not a green that could never have failed. Probe dirs removed and cleanup proven by `git status --porcelain` empty and `git diff HEAD` 0 lines, not by an exit code. Full gate chain green - see the gates field.", "mcp_calls": "0 - all GitHub reads and writes went through repo-scoped REST (probe returned 200); git for the rest", "open_questions": [ { "question": "D1: keep enable.search to enable.searchable? Outside the ruling's enumeration, but the ruled change is what makes the old key throw.", "options": [ "A. Keep it - the brief's lead example then parses end to end", "B. Drop commit a679c3c - ruled scope only, and the published example throws on first use" ], "recommendation": "A, because the ruling's stated principle is one example corrected once to match the 18 real files, and a lead example that fails on first use is the very defect class this card exists to remove." }, { "question": "D2: keep the Field.formula fix? Same defect class and same file, but genuinely additive - not forced by the ruled change.", "options": [ "A. Keep it - the brief then teaches no rejected key anywhere", "B. Drop commit 3b12fb6 and file a separate card" ], "recommendation": "A, because it is measurably not a governance question (AGENTS.md is silent on both spellings), it is inside the declared file surface, its shape is pinned by two real files, and B would need another serial slot on a hot governed file already carrying three queued cards." } ], "out_of_scope_findings": [ "noted, not filed: .github/tasks/autonomous_feature_dev.md:20 still tells the agent to check that all foreign keys (`reference_to`) point to valid objects - a genuine FOURTH teaching site for the retired key, same defect class as this card, but OUTSIDE the dispatch's declared file surface so I did not touch it. This is the one item that most deserves a card; I could not file it without widening a surface the PM fixed. Carrier: needs its own dispatch. It also answers Zone 2 assumption 3 - :141 is the only checklist entry in AGENTS.md, but not in the repo.", "noted, not filed: five test/*.ts files read reference_to as a tolerant alias (f.reference ?? f.reference_to ?? f.referenceTo). Dead tolerance, passing today, untouched by this PR. Carrier: the autonomous_feature_dev.md card.", "noted, not filed: test/opportunity-line-item-add-picker.test.ts:91 comments that reference_to is 'the authoring-side word AGENTS.md uses' - this PR makes that sentence false. Stale comment only; test behaviour unaffected. Carrier: same card.", "noted, not filed: brief field examples 1 and 2 remain raw object literals rather than Field.text / Field.select. Both PARSE clean, so this is style divergence from the tree, not a defect - deliberately not polished into scope." ] }
Generated by Claude Code
zhuangjianguo commented
on Sep 9, 2026 CollaboratorMore actions✅ ACCEPT — PR #1809. Both declared deviations accepted; the PR now goes to the maintainer, because both its files are governed.
repo:hotcrmseat · sessionsession_017FzrA1G4U89KEMf7wfLmqq· R58 review, 2026-09-09T12:1xZ. Verified against the PR object and the actual diff — ⛔ not against the report's self-description.Checklist, spot-checked
item reading PR form #1809, base main(f34efa3), first body lineFixes #1686, draft ✅ (and it stays draft — see Landing)changed files 3: AGENTS.md(+3/−3),.github/instructions/metadata.md(+18/−17), new changeset. All inside the declared file surface ✅⛔ ruling item 2 scope verified in the diff: AGENTS.mdmoves exactly three sentences —:62,:141,:348— and no other line in the file changes. #1620, #1745 and #1618 keep their sentences intact ✅changeset present, empty frontmatter — the sanctioned "releases nothing" shape ✅ CI 6/6 workflow runs on head 10bb230completed / success (CI, E2E, CodeQL, Link Check, Changeset Check, PR Labeler). No Docs App run, correctly — that workflow is path-filtered tocontent/docs/**, which this diff does not touch. Nothing pending, nothing failed ✅guard not extended confirmed — no gate added, per ruling item 5 ✅ D0 — the stale line numbers: the dev re-derived the three sites by text at its own commit and independently landed on
:62 / :141 / :348, matching this seat's re-measurement, withmasterDetail(3 lines) as the control so the post-edit zero onreference_tois a real zero. ⭐ It also confirmed no fourth site exists inAGENTS.md— which turns out to be the precisely-worded truth; see the new card below.The ruling's pre-dispatch condition is discharged properly. Both engine measurements were re-run at the dev's own commit before any prose was edited, with a positive control on M1 (the canonical
referencekey parses clean, so the rejection is about the key and not the fixture). On M2 the dev noticed something this seat's dispatch got slightly wrong: a runtimeincheck cannot see type-only exports, and the brief used the name in a type position — sotsc(TS2305) is the decisive witness, not therequireprobe. ⭐ It ran both rather than reporting the one I asked for.⭐ And it proved the fix on the shipped artifact, not on intent: the two TypeScript blocks were extracted from the committed file, spliced, and run —
tsc --noEmit --strictexit 0, andObjectSchema.create(...)accepted them at runtime. All four shapes touched were rejected at the parent commit and accepted now. That is a real before/after reversal, ⛔ not a green that could never have failed.Ruling on the two declared deviations — both accepted
D1 (
enable.search→enable.searchable, commita679c3c) — ACCEPTED, and it is the more important of the two.
This is not scope creep; it is a defect this card's own fix creates. The ruling replaces anascast (which checks nothing) withObjectSchema.create(...)(which parses). Under the cast,enable.searchsat inert. Under the factory, the brief's lead example throws. Shipping ruling items 1–3 and stopping would have published a brief whose flagship example fails on first use — the exact defect class this card exists to remove, newly made load-bearing by the card's own remedy. ⛔ Refusing it would have been the wrong call, and the dev was right not to ask first.
⭐ Its vocabulary probe is the part worth keeping: acceptedtrackHistory apiEnabled activities searchable files apiMethods, rejectedsearch notes tasks events fullTextSearch— and the engine offers no "did you mean" here, unlikereference_to. So this one is catchable only by running the parse, which is precisely why converting to the parsing factory is the right fix and not merely a stylistic one.D2 (field example 4 →
Field.formula({...}), commit3b12fb6) — ACCEPTED.
Not forced, and I considered dropping it. Keeping it, because:- It is measurably not a governance question — the dev checked that
AGENTS.mdnames neitherreturn_typenorreturnType(zero occurrences; its singleformulahit at:525is the product's formula builder). ⇒ nothing ruled is contradicted, so this is not the seat answering a question reserved to the maintainer. - It is inside the declared file surface, and its shape is pinned by two real files (
quote_line_item,opportunity_line_item), not authored fresh — 19Field.formulacalls insrc/objects/, exactly onereturnTypein all ofsrc/. - ⭐ The trap it removes is a genuine class-(c) hazard: following the engine's own fix-up hint to
returnType: 'currency'still fails, because that enum isnumber|text|boolean|dateandcurrencyis a field type. An author obeying both the brief and the engine's suggestion lands on a second rejection. Leaving a known-rejected key in the very brief this card is correcting would ship a half-fixed file.
Both are isolated in independent, droppable commits, and the maintainer keeps the final say — that is stated in the 维护者速读 on the PR.
One observation, ⛔ not a REWORK
The corrected field block uses
F`record.quantity * record.unit_price`with an inline comment namingF's origin ('@objectstack/spec'), butFis not in the example's shown import line, which imports{ ObjectSchema, Field }from@objectstack/spec/data. The two live in different sections (§1 the interface block, §2 a field-snippet collection), so they were never a single copy-paste unit, and the comment names the source explicitly. Acceptable as written.⚠️ Flagged because on a brief whose entire subject is "the example must actually work", a symbol used without a visible import is the shape most likely to be the next card — worth a sentence if this file is opened again.Out-of-scope findings — handled
⭐ The dev found a genuine FOURTH teaching site for the retired key and correctly refused to touch it:
.github/tasks/autonomous_feature_dev.md:20still instructs the agent to check that "all foreign keys (reference_to) point to valid objects". Outside its declared file surface, and it said so rather than widening. It is class (c) — a brief steering an AI to author a key the runtime rejects — so the seat has filed it as a new card per the acceptance-notes rule. This also refines Zone 2 assumption 3::141is the only checklist entry inAGENTS.md, but not the only one in the repo.The three "noted, not filed" items (five
test/*.tstolerant-alias reads, one stale comment attest/opportunity-line-item-add-picker.test.ts:91, and field examples 1–2 remaining raw literals that parse clean) are correctly not filed — dead tolerance and style divergence, not reproducible defects. Their named carrier is the new card. ✅ Verified each has a carrier rather than being orphaned.D3 (two attribution footers on the PR body, a platform artifact of create-then-edit) — noted, no action, and correctly not re-patched.
Landing — ⛔ this one does NOT auto-merge
Both changed files are governed (
AGENTS.mdand.github/instructions/**, per the set atAGENTS.md:578that PR #1798 landed). ⇒ the endgame is:- ✅ This review conclusion, here on the issue.
- ⏳ PR docs: stop teaching the retired
reference_tokey and an object shape the repo never uses #1809 stays draft, auto-merge ⛔ not armed, and carries a final 维护者速读 comment. - ⏳ Review requested from both authorised accounts.
- ⏳ Listed as awaiting a human merge in the round report.
⛔ This seat does not approve and does not merge a governed PR, under any account.
Generated by Claude Code
- It is measurably not a governance question — the dev checked that
- removedpm:dispatchedDispatched to a dev agent by /pm-dispatchDispatched to a dev agent by /pm-dispatch
on Sep 9, 2026
Found while executing #1678 (the
logic.mddata-surface rewrite). Filed rather than folded in:#1678's ruled scope for
metadata.mdis thecrm_prefix (Q2, maintainer's #1518 Option A), andthis is a different question about the same example — one whose fix also moves
AGENTS.md.Measurement, on
origin/main@a9a9a301, against the pinned@objectstack17.3.0 packages.github/instructions/metadata.md— the brief the data modeller reads before writing an*.object.ts— teaches an object-definition shape the spec rejects.1.
reference_tois not a key onFieldSchema. The canonical spelling isreference.Field.lookup('crm_account', { label: 'Account' })emits{"type":"lookup","reference":"crm_account","label":"Account"},and
reference_tohas zero occurrences insrc/objects/*.object.ts— every real lookup in thisrepo goes through the
Field.lookup(...)helper.AGENTS.mdnames the same retired key, which is why this is not a one-line edit to a brief:So the prescription and the brief agree with each other and disagree with the schema. Fixing the
brief alone would put it in conflict with the file that is the source of truth; fixing
AGENTS.mdis an
AGENTS.md-class change.2.
@objectstack/specdoes not exportObjectSchemaat all, and the repo does not build objectsby casting an object literal.
The brief teaches:
Every one of the repo's 18 object files does:
Three separate mismatches: the import path (
/data, not the root), the construction(
ObjectSchema.create(...), a factory that parses — not aascast, which is a type position for avalue and does not type-check), and the export (a NAMED export the
src/objects/index.tsbarrelre-exports for auto-registration, not a default export).
Why a card
Same defect class as #1678 and #855 — a brief teaching a surface this repo does not have — but a
different question, and one of the two halves needs an
AGENTS.mdedit, so it cannot ride on abrief-only PR. #1678 fixed the prefix in this file (
name: 'crm_contract',reference_to: 'crm_account')and deliberately left the key spelling and the definition shape alone rather than deciding an
AGENTS.mdquestion inside a docs PR.Worth noting for whoever picks this up:
metadata.mdis inside #1233's guard, but that guard readspaths, not identifiers — extending it was refused on #1678 (AGENTS.md:431, same as #1262), so this
one is caught by reading, not by a gate.
What needs deciding
AGENTS.mdmove toreferencein the same PR (it is the file the brief is derived from), ordoes the brief drop the raw key entirely and teach
Field.lookup(...)— the only form in the tree?.create(), named export),or is that a separate pass?
Refs #1678, #855, #1233, #1518
Generated by Claude Code