Repository navigation
Description
来源:宣传视频车道 #147(一句话新模块·请假管理)为改版取景所做的只读侦察。未改动任何平台代码、未改任何配置,本单为纯只读观察。
本单只描述现象,不预设修正方向。 是否算缺陷、以及该往哪个方向处理(对象自动可报表、按需生成 dataset、保持显式声明并在别处补齐、或仅改文档与提示),全部留给负责人裁定。故不带
pm:queue——请先分级,不要被自动流程当成待开发任务直接领走。
现象
一位 AI agent 依据一句业务需求,在既有 CRM 应用里长出了一个完整的请假模块:对象 crm_leave_request(15 字段)、审批流、5 个 profile 的权限声明、4 个视图、写进既有应用导航的菜单项。这些在应用里都能用。
但这个新模块在报表里选不到。
报表构建器本身是齐全的——Report type(Matrix)、Dataset、Values(measures)、Rows/Columns(dimensions)、Chart type,左侧还有带合计行的实时预览。问题在它的数据源入口:它只接受 dataset,不接受对象。
Dataset 下拉里共 13 项:
| 类别 | 数量 | 说明 |
|---|---|---|
平台级 sys_* |
4 | User / Organization / Session / Audit Log Metrics |
| 业务对象的 | 9 | account / case / contact / event / forecast / lead / opportunity / product / task —— 每一个都在 src/datasets/ 里逐个声明过 |
| 请假的 | 0 | —— |
机械核查:src/dashboards/、src/reports/、src/datasets/ 三个目录里零 leave 声明(唯一 grep 命中是 shared-widgets.ts 注释里的英文单词 "leave",假阳性)。
于是「本季度各人请假天数」这类报表现在出不来;要出,必须先另写一份 leave dataset 声明。
为什么记下来
同一个模块,运行时的那一面是齐的(表单、审批、视图、导航、记录权限都能用),分析的那一面是空的——两者的开通方式不同:前者由对象与视图声明带出,后者要再声明一次 dataset。
对一个「按描述长出模块」的平台,这意味着任何新长出来的对象,其分析能力都不随模块一起到位,需要第二次声明。这是本次侦察观察到的事实;是否属于有意的设计取舍(例如 dataset 承担了治理、RLS、度量语义等对象本身不表达的东西),本单不判断。
相关的界面观察(同为只读)
- widget 属性面板的 DATASET BINDING 帮助文本原文:「Bind a governed dataset. When set, it takes precedence over the inline object query above …」——即 widget 另有一条直接查对象的 inline query 路径。
⚠ 未验证该路径能否指向crm_leave_request:验证需要新建或修改一个 widget,属改配置,超出本次只读范围。如实记为未验证,不作推断。
复现最小路径
- 在一个已有若干 dataset 的应用里,新建一个对象(本例
crm_leave_request,15 字段),并为它声明视图与菜单项; - 打开报表构建器,展开 Dataset 下拉;
- 新对象不在列表中——列表里只有
sys_*与那些已被显式声明过 dataset 的业务对象。
取证环境
2026-08-31,载体 objectstack-ai/hotcrm,钉 @objectstack/* 17.1.0。纯只读 + 截图,未改数据、未改配置、未改源码。
邻近既有单(已查,非重复)
- Analytics: a dataset dimension on a dotted relationship path (
crm_account.industry) renders raw stored values — the same field as a local dimension renders its option labels #5144Analytics: a dataset dimension on a dotted relationship path renders raw stored values …(已声明 dataset 之后的维度渲染问题,与本条的入口可用性不同;已以not_planned关闭) - 审批回写(系统身份)不触发共享规则物化,「批准后团队看不见」——平台只记一条日志、无补偿、无声明式手段 #13533 / [finding] 删除记录后,它的审批单仍留在审批收件箱:pending 与 approved 两种都留,记录引用退化为原始 id #13568 —— 同一次 🔗 Broken links detected in documentation #147 取证中发现的另两条,均与本条无关
Activity
huangyiirene commentedon Aug 31, 2026
⚖️ 裁决记录 — C:显式 dataset 声明维持为设计意图;把「dataset 是模块完整性的一部分」写进发布技能与文档
出处:维护者 2026-08-31,live PM chat,总监席第 7 场决裁批 #15,逐字:「同意」(对本批三张按呈报推荐整体放行;本卡呈报推荐为 C 先行)。录裁:director seat, session
session_01KGtaLpkW1mycWgkbSb3H6t。裁定内容
四维分析(呈报件存档)
状态转移(同笔)
needs-user-decision→pm:queue。本卡无domain:*—— 留分诊首触路由。Routing suggestion (triage's call, not this seat's): the deliverable is published-skill + docs teaching (module-completeness checklist gains a dataset item), which reads asdomain:skillsfor the published-skill half; the unverified widget inline-query observation stays recorded, not acted on.Generated by Claude Code
os-warren commentedon Aug 31, 2026
分诊补车道 →
domain:skills· p2 · documentation。状态pm:queue保持不动。先说一句给后来读卡的人:本卡正文写着「⛔ 故不带
pm:queue——请先分级,不要被自动流程当成待开发任务直接领走」,而卡上确实挂着pm:queue。这不是自动流程误领 —— 2026-08-31 维护者已在本卡评论里裁决(总监席第 7 场决裁批 #15,逐字「同意」,本卡呈报推荐 C 先行),并在同一笔把needs-user-decision→pm:queue。正文的那句禁令是立单时的状态,已被裁决取代。我按流程在记录处置前重读了正文之后的全部评论,正是这一步拦住了误判 —— 只看标签和标题,这张卡看起来像「被抢跑的未分级卡」,实际是「已裁决、只差车道」。
锚定。 采纳裁决里的路由建议,并且我独立同意它:C 的交付物是发布技能 + 文档的「长模块」路径把 dataset 声明列入模块完整性清单 —— 主体是 AI 在创作当时读到的指令面 ⇒ 技能根 ⇒
domain:skills。content/docs/**的半边随卡,由 skills 席在认领评论申报文件面。裁决要点,原样进派单(⛔ 不得重开):
定级 p2。 裁决的 ③ 轴给了理由,我照抄它的判断:今天的状态是最糟的一种 —— 应用面看着齐、分析面静默缺失,正是 AI 批量犯错被掩盖的温床。C 把完整性写进结构化教材,是结构性防错,且成本是最小的那个。不判 p1:无线上故障,样本 = 1,且来自演示取景侦察而非客户报告(裁决自己也如实标了这一点)。
验收判据建议(裁决未给,属分诊补):改完之后,一个 AI 按发布技能长一个新模块时,dataset 声明应当和视图、菜单项一样是清单上的一项 —— 而不是一段读者可以略过的说明散文。若最终落成的只是文档里加一段话,那 ③ 轴的防错效果就没拿到。
crm_leave_request,立单方如实标注为「验证需改配置、超出只读范围」。⛔ 本卡不得把它当成既有绕法写进教材 —— 要么先验证,要么不提。Generated by Claude Code
claude commentedon Aug 31, 2026
Claim (dev): issue #13696
Session:
session_01Msg17tAHJ3jVTYFgHydCm2Branch:
claude/issue-13696-dataset-module-completenessWorktree:
objectstack-issue-13696(baseorigin/main@4ab8b59b)Located file surface (declared per the PM claim 5483913969, which left the exact files to this dev):
skills/objectstack-ui/SKILL.md— the landing checklist. The published grow-a-module completeness list is the CRM UI Blueprint (Metadata-First) table, framed verbatim as "the default for 'build a complete metadata app UI' tasks". It already carries rows for the two surfaces the acceptance criterion names —Multi-view object UI(src/views/*.view.ts) andApp navigation(src/apps/*.app.ts) — plusDashboardsandReports, but no row for the dataset those two bind. That omission is exactly the card's finding, at exactly the standing the criterion requires. Fix = one new peer row.content/docs/getting-started/build-with-claude-code.mdx— the docs half of the grow-a-module path (section "Beyond the first app — one skill per metadata domain", whoseobjectstack-uiprompt row currently asks for a dashboard with no dataset in sight).scripts/check-skills-token-ratchet.mjs— see the budget note below; touched only for itsCEILINGSrow, no logic change.Zone-2 premise: PM's belief FALSIFIED in its locative half, card premise INTACT. The grow-a-module teaching is not in
skills/objectstack-ai(that package is the AI-metadata authoring domain — agents, tools, knowledge sources — not "an AI grows a module"). It is theobjectstack-uiblueprint table above. The substantive half of the premise holds: datasets are not a checklist item there today (git grep 'src/datasets'overskills/**returns zero hits across the whole published catalog). So a PR is owed, on a different file than predicted. Notskills/objectstack-pm-dispatch/**— the clause-① face is untouched.Clause-②: confirmed no. Criterion read on
origin/main(.claude/skills/pm-dispatch/references/contract-review.mdline 7): the label attaches to changes making falsifiable operator / contract-semantic claims, and explicitly not to plain inventory, spelling or formatting. The new row is an authoring-inventory item; it asserts no runtime behaviour that is not already stated verbatim in the same file today.Budget note, surfaced now rather than at report time.
skills/**is priced by a second, independent control the dispatch budget does not describe:check-skills-token-ratchetis shrink-only per file, andskills/objectstack-ui/SKILL.mdsits at 25113 / 25125 — 12 tokens of headroom, i.e. ~48 bytes. A table row is ~200. The gate's own text names two ways out: pay by genuine deletion in the same file, or raise the ceiling in a PR whose body quotes a maintainer ruling. I am taking the cheapest honest mix — pay most of it by deleting a sentence in the same file that is already redundant inside its own paragraph, then raise the ceiling by the small remainder, quoting this card's ruling (comment 5475439419, batch #15, verbatim 「同意」) and printing the arithmetic in the PR body, per the two precedent rows already in that table. ⛔ No self-expansion of the PM's +20-net-line budget: the skills-side diff is +1 net line. The raise is called out for the PM in the report as the one budget-adjacent judgement in this card.Scope held: Option C only. ⛔ No objects-auto-reportable, ⛔ no dataset auto-generation rider, ⛔ the widget inline-object-query path is not taught (left unverified, omitted).
Generated by Claude Code
claude commentedon Aug 31, 2026
os-dev-report
{ "issue": 13696, "status": "done", "branch": "claude/issue-13696-dataset-module-completeness", "pr": "https://github.com/objectstack-ai/objectstack/pull/13972", "premise_still_valid": true, "summary": "Option C landed as a checklist item, not prose. The catalog's module-completeness list is skills/objectstack-ui/SKILL.md section 'CRM UI Blueprint (Metadata-First)', framed verbatim as 'the default for build a complete metadata app UI tasks' and already carrying rows for the two surfaces the acceptance criterion names (src/views, src/apps) plus dashboards and reports. It had no row for the dataset the last two bind: git grep 'src/datasets' over the whole published catalog returned ZERO hits before this PR. Added one peer row, 'Analytics dataset' (src/datasets/*.dataset.ts), placed above Dashboards and Reports; the Reports row shed the 'Bind a dataset' sub-clause since the obligation moved up to a line item. Skills diff is +1 net line against the PM's +20 budget. Docs half: content/docs/getting-started/build-with-claude-code.mdx (the grow-a-module path) gains a habit bullet, 'A module is not finished until its analytics face exists', and its objectstack-ui prompt row now asks for the dataset before the dashboard -- the previous prompt was the exact request that silently produces nothing. +8 net lines against the ~30 budget. PM ZONE-2 BELIEF FALSIFIED IN ITS LOCATIVE HALF, card premise intact: the grow-a-module teaching is NOT in skills/objectstack-ai (that package is the AI-metadata authoring domain -- agents, tools, knowledge sources -- not 'an AI grows a module'). Its substantive half held, so a PR was owed, on a different file than predicted. Not the clause-1 face (skills/objectstack-pm-dispatch untouched). Clause-2 confirmed NO against the criterion read on origin/main: the row is authoring inventory and asserts no runtime behaviour not already stated verbatim in that file. Fences held: no option A, no option B rider, and the unverified widget inline-object-query path is omitted rather than taught. THE ONE THING THE PM SHOULD LOOK AT is the token ratchet -- see open_questions.", "tests": "Gate union derived mechanically (no hand list) on the FINAL head 0e8a4e97 via `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack`; the derivation is byte-identical before and after the commit (diffed). 39 families across 29 workflow files. Tier probe on the actual located paths: 'no path-derived mandate' -- no fable mandate fired. RESULT: 36 green on the first sweep (each exit code captured by redirect-then-capture, never through a pipe), including check:pm-governed-merges, check:skill-frame-sync, check:skill-identifier-liveness, check:skill-compatibility, check:corpus-claim-drift, check:doc-authoring, check:docs-single-h1, check:role-word. 4 returned PREREQUISITE NOT MET (unbuilt workspace packages -- each says in its own text that nothing was measured and it is not a finding); after turbo build over @objectstack/spec, @objectstack/lint, @objectstack/formula, @objectstack/client-react, @objectstack/client all 4 are green, quoted from their own verdict lines: 'check:doc-formula-expressions: 22 record-scoped formula example(s) across 427 files / 1451 TS blocks judged clean'; '26 ObjectSchema.create example(s) in 230 marked block(s) ... carry an os validate-clean security posture'; '230 generated files in sync with packages/spec'; '260 prose examples type-check across 3 surface(s) -- every marked block parsed, so tsc ran the SEMANTIC pass on all of them'. 1 is structurally NOT MEASURED locally, read as neither red nor green: check-test-completeness grades a saved `turbo run test` log and exits 3 when handed none; its own text says the branch is unreachable in CI and 'there is nothing here to fix'. RATCHET FAMILY RE-RUN ON THE COMMITTED HEAD 0e8a4e97, after the last commit rather than before it: 'check-skills-token-ratchet self-test: 64 cases pass'; 'skills/objectstack-ui/SKILL.md is 25143 tokens (ceiling 25143; headroom 0)'; '38 authored bundle file(s) within their ceilings'. Self-derived beyond the dispatched list because the diff edits a gate script: check-ratchet-remedy-authority (its own self-test plus the sweep -- 'OK ... 12 mark the expanding remedy MAINTAINER-ONLY, 6 turn it down outright'), and check-nul-bytes ('OK, scanned 7660 text file(s); no raw ASCII control bytes') plus a hand control-byte grep over the three changed files, clean. The ratchet script carries no vitest suite -- git grep over test files returns none; its --self-test IS its suite and it is in the list above. No ablation was run: this is teaching text with no runtime behaviour to mutate, so the template's ablation field has no honest value here rather than a manufactured one. Heavy work went through scripts/pm/os-verify-lock.sh (slot issue-13696-gates, waited 0s each time); verdicts read from its VERDICT lines, not from bare $?.", "mcp_calls": "0 -- the whole run went through the container's repo-scoped REST channel (probed green at the start with GET /repos/.../issues/13696, HTTP 200) plus git. Card body, both binding comments, the four sweep-flight precedent PRs and their labels, the claim comment, the dedupe listings, the PR creation, the label write and every read-back are REST. Zero MCP GitHub calls, so zero GraphQL pool burn.", "open_questions": [ { "question": "The published-skills TOKEN ratchet is a control the dispatch budget does not describe, and it bites here. check-skills-token-ratchet is SHRINK-ONLY per file and skills/objectstack-ui/SKILL.md had 12 tokens of headroom (25113/25125) -- about 48 bytes, against a table row of ~200. So the honest +1-line change cannot land without either paying by deletion or moving the ceiling. The gate itself names both routes and reserves the second: 'The other direction lands only in a PR whose body quotes a maintainer ruling authorizing it. MAINTAINER-ONLY'. I took the cheapest honest mix and am flagging it rather than letting it pass as routine, because moving a MAINTAINER-ONLY ceiling is exactly the kind of call a dev should surface: net +120 bytes (+204 new row, -7 Reports row, -77 deleted duplicate sentence), 25113 -> 25143 tokens, ceiling 25125 -> 25143, landing at zero headroom. Authorizing ruling quoted in both the CEILINGS row comment and the PR body: this card's own ruling, comment 5475439419, maintainer 2026-08-31 director seat batch #15, verbatim, which MANDATES this text. Is that the disposition you want?", "options": [ "A -- accept as landed: one row, +18 to the ceiling, ruling quoted in the row comment and the PR body, matching the two precedents already in that table (objectstack-automation 12643, objectstack-pm-dispatch 14391, both raised on a quoted ruling with the arithmetic in the raising PR).", "B -- refuse any raise: I delete a further ~72 bytes of dataset prose from the same file so the ceiling stays 25125. Available, and I costed it -- but the only remaining candidates are load-bearing sentences in the Dashboards / Dataset-Bound Widgets sections, so it buys a green number by removing real teaching from the surface this card exists to strengthen.", "C -- escalate the raise to the maintainer as its own question before landing, on the view that this card's 'agree' authorizes the TEXT but not specifically a ceiling move." ], "recommendation": "A. Real business need: the pull is the recorded one -- an agent shipped a module that was invisible to the report builder -- and it is the maintainer's own ruling that requires text here, so refusing the 18 tokens refuses the ruling. Long-term soundness: the gate documents this exact route and two rows in the same table already took it; using the documented path keeps the ratchet legible, whereas B pays a lint number in teaching quality, which inverts what the ratchet is for. Hard to get wrong: a checklist row is the structural guard -- the criterion's whole point is that prose can be skipped and a line item cannot. Startup scope discipline: this is the smallest shape that discharges the card, +1 net line and 18 tokens, well inside the 2026-08-21 ruling against expanding a lot for a small feature -- which is also why I did not take C: C spends a maintainer turn on 18 tokens the maintainer has already ruled must exist. If you disagree, B is a one-commit change and I would take it over stalling." } ], "out_of_scope_findings": [ "filed as #13974: the published project-layout tree in skills/objectstack-platform/SKILL.md lists dashboards/ and reports/ but not datasets/ -- same defect class, different reading path (layout, not assembly checklist), and PR #13972 does not cover it. Filed rather than fixed in place: the fix needs a SECOND ratchet ceiling move (that file has 18 tokens of headroom against an ~85-byte tree line), and stacking an unrelated ceiling raise into a tightly scoped card is not a call to make unilaterally. Unassigned, no labels, left for triage." ] }Generated by Claude Code
docs(skills): give datasets/ a home in the published project-layout t…