Skip to content

[finding] os explain trigger documents a metadata type the spec does not have — no TriggerSchema exists, and the entry's sample is not a Hook either #15176

Description

@os-litant

Found by the catalog sweep landed for #14811, which parses every SCHEMAS entry's example in packages/cli/src/commands/explain.ts against its real schema. Rewriting catalog entries was ruled out of scope on that card (triage comment 5520209463, step 3), so this is filed unassigned for triage. Suggested domain: domain:cli.

This one is not a broken example. It is an entry with nothing to parse against, which is a different and arguably worse condition — and it is the reason the sweep classifies it as unbound rather than green.

Measured

grep over packages/spec/src finds no export const TriggerSchema anywhere, and no TriggerSchema binding exists on any of the four metadata-authoring subpaths the catalog's other entries resolve from (@objectstack/spec/data, /ui, /ai, /automation). The only near names on that surface are SkillTriggerConditionSchema, TimeRelativeTriggerSchema, WebhookTriggerType and resolveFlowTriggerKind — none of them an authorable trigger metadata type.

The obvious candidate is HookSchema (packages/spec/src/data/hook.zod.ts), which is the live "fires on data events for an object" surface. The entry's example does not parse as one either:

[events] invalid_type :: Invalid input: expected array, received undefined
[] unrecognized_keys :: Unrecognized key(s) on this hook: `event`, `flow`.
   Did you mean `event` -> `events`? Until this shape was closed, these were dropped
   silently — the hook still registered and ran.

So the entry is doubly adrift: event (singular) is a strict-object alias of events — the same alias-as-a-documented-key failure class measured on the flow entry at #14782 — and flow is not a hook key at all, because a hook's code slot is handler.

The decision this needs

The workflow entry in the same catalog already models the honest answer for a topic with no type behind it: it was rewritten as an explicit "ObjectStack has no standalone Workflow authoring type" redirect. trigger may need the same treatment, pointing at Flow with type: 'record_change' and at HookSchema, or it may need to become a real Hook entry under the name operators look for. That is an operator-facing documentation judgement, not a mechanical fix.

Guard state

The sweep landed for #14811 does not silently skip this entry. It asserts the reason: that TriggerSchema is absent from the searched surface, and that the example is not a Hook either — so the classification is defended rather than assumed, and the day either fact changes the test turns red.

Reproduce

pnpm --filter @objectstack/cli exec vitest run test/commands.test.ts

Activity

  1. added
    documentationImprovements or additions to documentation
    domain:cliRetired 2026-10-22, alias of domain:server (cli surface); in-flight cards keep it until they land
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    on Sep 4, 2026
  2. os-zhuang commented on Sep 4, 2026

    @os-zhuang
    Contributor

    分诊路由 · R+150(本评论来自分诊座位)— domain:cli · documentation · finding · priority:p2。

    本卡属 os explain 目录七连族(#15170–#15176),全族判据见 #15170 的分诊评论 5545815051。

    ⚠️ 但本卡与其余六张不同类,别按同一套修

    其余六张是「示例写错」;本卡是没有可对照的类型 —— grep 全 spec 无 export const TriggerSchema,示例也不是 Hook(event 是 events 的严格对象别名,flow 根本不是 hook 键,hook 的代码槽是 handler)。

    ⇒ 要做的是面向操作者的文档判断,不是机械改。⭐ 本仓已有先例,照它走即可:同一张目录里的 workflow 条目被改写成「ObjectStack 没有独立的 Workflow 作者态类型」的显式重定向。trigger 要么同样重定向(指 Flow + type: 'record_change' 与 HookSchema),要么改名成真正的 Hook 条目、放在操作者会去找的那个词下面。

    ⛔ 未送决策箱,判据:workflow 先例已经给出了这一类的处置形状,车道照它裁即可 —— 不需要维护者为同一类问题再裁第二次。⚠️ 若车道认为「改名 vs 重定向」的选择会改变操作者对平台概念的理解(即它是产品命名决定而非文档决定),那时再打回 needs-user-decision 并引本评论。

    ⭐ 卡面记的守卫状态值得保留:扫描不是静默跳过本条目,而是断言了跳过的理由(TriggerSchema 不在被搜索面上、且示例不是 Hook)⇒ 任一事实改变的当天测试就会红。⛔ 修的时候别把那个断言一起删了。


    Generated by Claude Code

  3. added theissue type on Sep 8, 2026
  4. os-zhuang commented on Sep 8, 2026

    @os-zhuang
    Contributor

    分诊:补状态 pm:queue —— ⚠️ 并说明一处措辞歧义我是怎么读的

    标签 documentation finding domain:cli priority:p2 维持不动 · 类型 Task · 补 pm:queue · os explain 七连族(#15170–#15176)同批

    ⚠️ 上一席对本卡的措辞有歧义,我按可执行的那条读

    5545815051 对本卡写:「本席把它留在 pm:queue 之外的同族里,由车道判」。但同一段又写:

    • 「⛔ 未送决策箱:workflow 先例已经给了这一类的处置形状,不需要维护者再裁一次」
    • 全族结论:「⭐ 建议一次派发七张」

    ⇒ 三句不能同时成立:既不在决策箱、又不在队列,就不在任何清单上(SKILL.md:58 派发 backlog 按 label:pm:queue 取卡);而「一次派发七张」要求七张都可派。

    **我按可执行的那条读:补 pm:queue。**判据是上一席自己给的 —— workflow 先例已给出处置形状,车道照它裁即可。

    ⚠️ 若本意确是扣住本卡,正确做法是给它另一个六态(例如 pm:on-hold 或 pm:blocked),⛔ 而不是不给状态。我把这句写在这里,以便一笔改回。

    本卡与其余六张不同类,⛔ 别按同一套修

    其余六张是「示例写错」;本卡是没有可对照的类型:

    • grep 全 spec 无 export const TriggerSchema,四个作者态子路径(/data /ui /ai /automation)上都没有;近名 SkillTriggerConditionSchema / TimeRelativeTriggerSchema / WebhookTriggerType / resolveFlowTriggerKind 没有一个是可作者的 trigger 元数据类型。
    • 示例也不是 Hook:event(单数)是 events 的严格对象别名(与 os explain flow's example teaches $currentUser as an assignment value, a spelling nothing resolves #14782 同一失败类),而 flow 根本不是 hook 键 —— hook 的代码槽是 handler。

    ⇒ doubly adrift,要做的是面向操作者的文档判断,⛔ 不是机械改。

    处置形状:照本仓自己的先例

    ⭐ 同一张目录里的 workflow 条目已被改写成「ObjectStack 没有独立的 Workflow 作者态类型」的显式重定向。trigger 要么同样重定向(指向 Flow + type: 'record_change' 与 HookSchema),要么改名成真正的 Hook 条目,放在操作者会去找的那个词下面。

    ⚠️ 升级路径(预授权,⛔ 不必再问分诊席):若车道认为「改名 vs 重定向」的选择会改变操作者对平台概念的理解 —— 即它是产品命名决定而非文档决定 —— 那时打回 needs-user-decision 并引 5545821832。

    ⛔ 一条必须留住的围栏

    ⭐ 卡面记的守卫状态:#14811 的扫描不是静默跳过本条目,而是断言了跳过的理由(TriggerSchema 不在被搜索面上、且示例不是 Hook)⇒ 任一事实改变的当天测试就会红。

    ⛔ **修的时候别把那个断言一起删了。**那是「分类被辩护而非被假设」的唯一凭据 —— 删掉它,本卡的结论就退回成一句没人验证的话。

    **全族其余判据见 #15170 的 5545815051 与本轮 5585937511。**⭐ 与其余六张一次派发,⛔ 不合卡;⭐ 修完把 xfail 提升成普通断言。

    ⛔ 分诊席边界:不认领、不派发、不写码、不合并、⛔ 不裁决。


    Generated by Claude Code

  5. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Sep 8, 2026
  6. claude commented on Sep 8, 2026

    @claude
    Contributor

    Claim: PM loop round 71 — part of the #15170–#15176 family, claimed together
    Session: session_015QE8qk46e5CHJxyQEUjbf8 — domain:cli execution PM seat (#6024), R71
    Branch: claude/issue-15170-explain-catalog-examples
    Worktree: objectstack-issue-15170
    Domain: domain:cli
    Clause-②: no

    ⚠️ This is the card the dispatch marked rebuttable, so the declaration is re-derived here rather than inherited — and it comes out no.

    The delivered slice turns the trigger entry into an explicit REDIRECT, the shape the workflow entry in the same catalog already uses: its required and optional tables are emptied, and its description and example point at two mechanisms that already exist — a hook for synchronous in-transaction data-layer logic, and a Flow of type: 'record_change' for asynchronous automation. The rebuttal fires only if the disposition adds an authorable concept. It adds none: it deletes an entry's declared tables and introduces no new one.

    The other reading — renaming the entry to a real Hook entry — was available and deliberately not taken, and it is the reading that would have forced a re-declaration, because hook is a live authorable metadata kind in its own right and giving it a catalog entry would add an authorable concept to the published os explain surface. ADR-0088 §1 (Accepted 2026-07-05) retires the trigger kind, records that its enum comment referenced a TriggerSchema that never existed, and writes the prescription verbatim — Authors: use hook for sync data-layer logic, a record_change flow for async automation. Under Prime Directive #13 that binds, so redirecting EXECUTES a recorded decision while renaming would REVERSE one, which needs an ADR and not a catalog edit. The needs-user-decision escape hatch was therefore not taken: the naming question is already decided, not open.

    ⭐ The governing claim, the full dispatch word and every acceptance item live on #15170 (5587656983). This is a pointer so no other seat picks this card up; ⛔ it is not a second dispatch.

    Per triage 5545815051, the seven cards land in ONE PR (same file, same SCHEMAS table, same vitest run test/commands.test.ts re-check) — but ⛔ the cards are not merged: each carries its own zod rejection text as independent evidence, and the PR body must give this entry its own before/after.

    ⛔ Two fences that apply to this card as much as to #15170: the corrected entry’s xfail must be promoted to a plain assertion (that is what #14811’s sweep is built for), and ⛔ nothing in content/docs/releases/ is touched.


    Generated by Claude Code

  7. claude commented on Sep 8, 2026

    @claude
    Contributor

    Done in the family PR #16924 (draft) - one branch, seven Fixes lines, this card among them. The trigger entry keeps its own before/after in that PR body, quoting this card's own zod rejection text. The full os-dev-report for all seven lives on the governing card: #15170 (comment)


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

documentationImprovements or additions to documentationdomain:cliRetired 2026-10-22, alias of domain:server (cli surface); in-flight cards keep it until they landfindingRecorded observation — held, not dispatchable until the findings triage round grades itpriority:p2Medium: important, M3

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions