Skip to content

docs(skills): name flow-filter-token-unknown for the flow-node filter position - #16803

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-16736-flow-filter-token-rule-id
Sep 8, 2026
Merged

docs(skills): name flow-filter-token-unknown for the flow-node filter position#16803
os-zhuang merged 1 commit into
mainfrom
claude/issue-16736-flow-filter-token-rule-id

Conversation

@hotlong

@hotlong hotlong commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Fixes #16736

skills/objectstack-query/rules/filters.md had exactly one filter-token-unknown
hit, and it sat in the paragraph immediately after "A flow node's
config.filter takes these tokens too" — with nothing re-scoping it, so it read
as the rule that fails an unknown token in a flow node. Since PR #16732 that
position is owned by a second rule.

The two ids stay distinct

Verified on the branch base by grep, both live:

position rule id declared in consequence
flows flow-filter-token-unknown packages/lint/src/validate-flow-filter-tokens.ts:65 template evaluator raises a guard refusal — "this node cannot run at all"
dashboards objects views reports datasets pages apps filter-token-unknown packages/lint/src/validate-filter-tokens.ts:65 literal reaches the engine, matches nothing, surface renders the silent zero

They are two ids because the two positions share neither a token vocabulary nor a
consequence. validate-filter-tokens.ts walks seven roots and deliberately not
flows
; validate-flow-filter-tokens.ts walks flows only and fires solely on
the call-position arm. Its module header states why widening the old id was
refused: "Widening the published id would make its meaning depend on the position
it fired in, which a machine consumer keyed on the id cannot see."

So the flow sentence names its own rule and the general paragraph is scoped with
"Outside a flow". The prose does not merge them into a single statement.

Wording — not the id distinction — was tightened to pay the token ratchet.

Readings (re-derived; the card's 238 was not inherited)

Branch base is b72226f48, newer than the b38821d1c the card was written
against; every number below was re-measured on it.

  • before: 250 lines, exactly one hit, at line 238
  • after: 251 lines, flow-filter-token-unknown at line 234, filter-token-unknown at line 239 (one hit each)

Published-bundle readings, both required for a skills/** diff:

reading before after delta
this file (rules/filters.md) 2136 tokens 2146 +10
whole shipped bundle 150584 tokens 150594 +10
ratcheted authored subtotal 139938 / 157098 139948 / 157098 +10

Ceiling for this file is 2149, so headroom went 13 to 3 — it fits without
deleting content, and the id distinction never became the currency:

✓ check-skills-token-ratchet: skills/objectstack-query/rules/filters.md is 2146 tokens (ceiling 2149; headroom 3).
✓ check-skills-token-ratchet: 36 authored bundle file(s) within their ceilings; 10 generator-owned file(s) measured, not ratcheted.

This is a one-line correctness fix, not an expansion: net +10 tokens on a 150k
bundle.

Gates — 20/20 green at 6cfd58efa

Derived in the worktree with node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (no paths); the derivation reproduced the dispatch's
list exactly — 20 commands, no additions. All run after the final commit, each
exit code captured by redirect before any pipe.

check:doc-formula-expressions first exited 3 — PREREQUISITE NOT MET, which is
not a reading. Built the two packages it names under scripts/pm/os-verify-lock.sh
(VERDICT command-exit 0 · held the lock 1s · waited 98s) and re-ran it to a real
exit 0.

Governed-surface predicate, quoted:

governed-surface predicate: 1 of 1 path(s) hit the register (5 surfaces, repo-agnostic).
  ⛔  GOVERNED — a human merge is the review record for this PR (#9495 regime).

Outside the runnable total and deliberately not read as clearance: 10 WIDE families,
42 artifact rosters, 2 families taking a value from the workflow.

No changeset — measured, not assumed

skills/** is not on the fast track, so it was measured rather than asserted:

  • zero files[] entries across packages/**, apps/**, services/** match /skill/i
  • symbol unique to this edit (Outside a flow, a whole-): 0 hits in any built dist/
  • positive control flow-filter-token-unknown (genuinely published via @objectstack/lint): 6 hits

Symbol zero, control non-zero, so the grep works and nothing published moves.
Labelled skip-changeset.

验收备注

  • The card's premise held, but its line number was re-derived rather than
    inherited: base moved b38821d1c to b72226f48 between dispatch and pickup.
    The file was still 250 lines with the single hit still at 238.
  • noted, not filed: the same passage's "renders a widget showing 0" clause and
    its isDateMacroToken / isContextToken advice are the ObjectQL-vocabulary
    story, so before this change a flow author who searched the skill for their
    build error would have landed on the wrong dialect's fix. The scoping added
    here removes that path; no separate card. 承接者: this PR.
  • The seven roots filter-token-unknown walks include dashboards and objects,
    two more than the five the card enumerates. The prose does not enumerate them,
    so nothing here depends on the difference; recorded only so the next reader of
    this passage is not surprised. 承接者: 无.

维护者速读(草稿)

改了什么 — 一个已发布技能文件里的一段话,一处规则 id。原文把「flow 节点的
config.filter 里写错 token,构建会以哪条规则失败」指向了 filter-token-unknown;
#16732 起,那个位置归 flow-filter-token-unknown 管。现在 flow 那句点名自己的规则,
原来那段用「Outside a flow」限定回它本来的位置。

为什么改 — 这段话是给 AI 作者看的。它构建失败、拿着 flow-filter-token-unknown
回来查技能包,原文会把它领到另一条规则的后果(「widget 显示 0」)和另一套词汇的修法
(isDateMacroToken / isContextToken)。两个位置的 token 词汇本就不同 —— 这正是当初
拆成两个 id 的原因 —— 所以散文里合并两者,等于把这次拆分要防的混淆重新教一遍。

风险与代价(含回滚) — 风险很低:改动只有一个文件、一段话,不含任何代码,不发布
任何 npm 包内容(已实测,非推断)。代价是 token 棘轮余量从 13 降到 3,这个文件以后再
加字需要先删字。回滚就是 revert 这一个 commit,没有任何下游依赖。

席位意见 — (留空,待席位填)

你要做的 — 只需确认一件事:为了让两个 id 的区分放得进 token 棘轮,我压缩了同一段
落的措辞(删掉「while authoring」「passing the」这类冗余,把「a value that is entirely
{...}」改成「a whole-{...} value」),没有删任何一条信息、也没有抬 ceiling。请确认
这个取舍可以接受 —— 裁决说「容不下时缩短的是措辞,不是那两个 id 的区分」,我照此执行。


Generated by Claude Code

… position

The passage sat directly after "A flow node's `config.filter` takes these
tokens too", so its rule id read as the one that fails an unknown token in a
flow node. Since #16732 that position is owned by a second rule.

The two ids stay distinct, because the two positions do not share a token
vocabulary or a consequence:

  - flows -> `flow-filter-token-unknown` (validate-flow-filter-tokens.ts),
    which fires only when NEITHER dialect resolves the token and whose
    consequence is a guard refusal: "this node cannot run at all";
  - dashboards/objects/views/reports/datasets/pages/apps ->
    `filter-token-unknown` (validate-filter-tokens.ts), which deliberately
    does not walk `flows` and whose consequence is the silent zero.

Collapsing them into one statement would re-teach the confusion the split
exists to prevent, so the flow sentence names its own rule and the general
paragraph is scoped with "Outside a flow".

Wording (not the id distinction) was tightened to stay under the published
token ratchet: 2136 -> 2146 tokens against a 2149 ceiling.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P58euzUXCVJNwmhuPC9DXY

hotlong commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

维护者速读(终稿)

席位复核记录:#16736 上的 ACCEPT 评论(skills 席,hotlong,session session_01P58euzUXCVJNwmhuPC9DXY,2026-09-08T06:24Z)。head 6cfd58efa

改了什么

一个已发布技能文件 skills/objectstack-query/rules/filters.md 里的一段话(+12/−11,一个文件,无代码)。flow 节点那句现在点名自己的规则 flow-filter-token-unknown,并带它自己的后果(「该节点根本跑不了」);原来那段用「Outside a flow」限定回它管的展示位,继续指 filter-token-unknown(后果:字面量进 SQL、匹配不到、界面显示 0)。两个 id 各自成句,不合并。为了放进 token 棘轮,同一段落的措辞压缩了五处(删「while authoring」「passing the」这类冗余),没有删任何信息。

为什么改

自 PR #16732 起 flow 位置归第二条规则管,原文却只写了旧 id,而且紧接在 flow 段之后没有任何再限定。拿着 flow-filter-token-unknown 的构建错误回来查技能包的 AI 作者,会被领到另一条规则的后果和另一套词汇的修法——两个位置的 token 词汇本就不同,这正是当初拆成两个 id 的原因。

风险与代价(含回滚)

风险很低:一个已发布 prose 文件、一段话,不进任何 npm 包(实测:改动独有片段在所有 dist/ 零命中,阳性对照 6 命中)。代价:该文件 token 棘轮余量 13 → 3(2146/2149),以后再加字先删字;上限未动。回滚 = revert 这一个 commit,无下游依赖。

席位意见

同意合并。席位对照 GitHub 逐项核过:两个 id 都在 origin/mainpackages/lint/src/ 各自第 65 行活着;分支文件恰好各一处命中(234 行 flow id,239 行通用 id),251 行;flow 那句「neither dialect resolves」与规则模块头「NEITHER {…} dialect can resolve」一致;裁决「容不下时缩短的是措辞,不是那两个 id 的区分」照做,压缩的五处逐一对照原文读过,信息无删减;20/20 门禁绿,check:skill-identifier-liveness 是承重那条;check-governed-merges --test exit 3(受管)。⚠️ 06:22Z 读 head 的 check run:24 项 success/skipped、5 项进行中(Lint & Repo Gates、Type Check ×2、Test Core ×2),无红;合并队列自己会再跑一遍,红的合不进去。

派发时席位的一处推断被证伪:「余量 13 够、不用删字」——诚实改写先超 8 再超 1,dev 按裁决只压措辞落到 2146。另一处订正:旧规则走的根是七个(dashboards、objects、views、reports、datasets、pages、apps),不是卡和裁决写的五个;散文不列举它们,不影响本改动。

你要做的

受管面(skills/**),按 #9495 规矩由人合:读 diff 那一段(两句各点名一个 id,「Outside a flow」限定),认可就批准或直接合并——席位在授权批准落地且全绿时挂 auto-merge,⛔ 不翻 ready、不入队。只问一字:两个 id 各说各的、措辞压缩换余量,你认吗——


Generated by Claude Code

@hotlong
hotlong requested a review from os-zhuang September 8, 2026 06:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation needs-user-decision skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

3 participants