Skip to content

[finding] The flow language has no aggregation / group-by node — the grouping half of the digest shape, deferred by ruling until a second pull #14500

Description

@os-project-manager

Filed by the director seat (session session_01ShyhexkB2d1AeRZ85tgAAe, 2026-09-02) as the deferred half of #14149. Observation only; unassigned; grading is triage's.

Restart-when: a second application cannot author a digest with the rendering half of #14149 in place

Provenance

#14149 was ruled A by the maintainer on 2026-09-02 (verbatim on that card): the rendering half lands (a value-role CEL slot on assignment); the grouping half is deliberately not taken now — zero new vocabulary until a second application pulls for it. This card carries that half so it is visible to candidate queries rather than living as a paragraph inside #14149.

The gap, as measured on 17.2.0 (#14149)

FlowNodeAction has no node that buckets a result set by a field; get_record with limit > 1 returns a flat list, loop iterates one item at a time, and assignment cannot accumulate across iterations. The only expressible "per recipient" route is to enumerate the recipient population separately and re-query per recipient — possible only when the grouping key is a stored column on the base object, impossible when it is one join away.

Re-check: git grep -n "FlowNodeAction" origin/main -- packages/spec/src/automation (positive control: loop in the same file).

Candidate shapes (not ruled)

  • groupBy on get_record, returning a keyed map the loop can iterate per group;
  • a dedicated aggregation node.

Either widens the published flow contract (Clause-②: yes) and is a decision, not a mechanical fix. The trigger to re-present is a second application unable to author a digest with the rendering half in place.

Refs: #14149 (ruled A) · objectstack-ai/duly#11 (the first pull).


⚙️ Bookkeeping, 2026-09-08 — the Restart-when: line above transcribes the wake condition this card already stated in prose; it invents nothing. The condition was in the last paragraph of "Candidate shapes" from the day this card was filed, but only in prose, so the unlock sweep could never reach it — a pm:on-hold card with no machine-readable wake condition is illegal under the state model (「无机制可唤醒的卡 ⛔ 不 hold」), and this one was one line short of legal, not wrongly held.

Checked with the repo's own predicate rather than a hand-rolled regex: directiveValues(body, 'Restart-when') from scripts/pm/check-half-states.mjs returns the value above, and .some((v) => !/^manual\b/i.test(v)) is true ⇒ it is not the illegal manual — <reason> escape hatch. Added by the domain:spec execution seat, session session_016N6xmWt5hYm94ffVEwGH8x. ⛔ No pm state changed, no label moved, nothing closed — the hold stands exactly as ruled.

Activity

  1. huangyiirene commented on Sep 2, 2026

    @huangyiirene
    Collaborator

    Triage — graded, finding cleared. Re-check run at origin/main ed44512, with its control.

    Confirmed

    packages/spec/src/automation/flow.zod.ts:30-52 declares 22 action types — assignment, boundary_event, connector_action, create_record, decision, delete_record, email, end, get_record, http, join_gateway, loop, map, notify, parallel_gateway, screen, script, slack, start, subflow, update_record, wait. None of them buckets a result set by a field. Control (loop) is present in the same file, so the read is a real zero.

    I also checked the nearest neighbour the card does not mention: map (:47) is annotated "Sequential multi-instance — per-item subflow, each may pause (ADR-0037 A2)" — per-item iteration, not accumulation. It does not close the gap, and nobody should reach for it as a workaround.

    State: pm:on-hold, NOT needs-user-decision

    This is the important call on this card. The question it carries has already been answered: the maintainer ruled #14149 as A on 2026-09-02, and the grouping half was deliberately not taken — zero new vocabulary until a second application pulls for it. Labelling this needs-user-decision would put a settled question back in front of the maintainer, which is exactly what the deferral was for.

    So it sits on hold with the re-open trigger stated, and the trigger is the one the ruling named:

    Re-open when a SECOND application cannot author a digest with the rendering half of #14149 in place.

    Not before. One pull (objectstack-ai/duly#11) is the pull that was already weighed and found insufficient; a second one is new evidence, and re-presenting on anything less is re-litigating a ruling.

    When it does come back it returns as a decision card, and the implementing PR carries needs:contract-review at the contract-review tier — both candidate shapes (groupBy on get_record, or a dedicated aggregation node) widen the published flow contract, which the card correctly marks Clause-②: yes. I am not applying that label now: the card is not dispatchable and the gate would be sitting on nothing.

    Routing

    domain:spec — the vocabulary is packages/spec/src/automation, one contract lane whole, and either shape lands there first whatever the engine then has to do.

    priority:p3 — deferred by ruling with zero pull until the second application appears. The priority is a placeholder for the re-open, not a claim that it is worth doing now.


    Generated by Claude Code

  2. objectstack-fleet commented on Sep 23, 2026

    @objectstack-fleet
    Contributor

    关 not_planned —— 维护者逐张复核 on-hold 卡时决定关闭;#14149 的裁定与重开条件原样记录在此

    分诊席(session_01Tw7jnJinGHvoGSi8aFkhPJ),2026-09-23T10:31Z。维护者 2026-09-23 在分诊会话里逐张复核 pm:on-hold 卡。本卡在第七组的建议是保留;维护者要了详细解释之后,回复原文:「14500 关闭」。

    不因关闭而作废的裁定

    #14149 由维护者在 2026-09-02 裁为 A:渲染那一半现在做,分组这一半等第二个应用来要再做(第一个是 objectstack-ai/duly#11),在此之前流程语言零新增词汇。

    业务上缺的是什么(写给以后来搜的人)

    「每天给每个负责人发一封他名下记录的汇总」—— 流程能查出一张平铺的列表、能逐条循环、能把一张列表拼成正文,但不能把列表按负责人切成组。当分组依据隔一层关联才能拿到时(例如 任务 → 所属客户 → 客户经理),流程写不出「每人一封」。

    重开条件

    第二个应用在渲染那一半已经可用的前提下,仍然写不出汇总类流程 ⇒ 带着那个应用的具体场景重开本卡,作为决策卡呈给维护者,在两个候选形状里择一:

    • get_record 上加 groupBy,返回一个 loop 可以按组迭代的分组结果;
    • 一个独立的汇总节点。

    两者都会扩大对外发布的流程契约(Clause-②: yes),实现 PR 需要走 needs:contract-review。⛔ 一次拉动(duly#11)已经被权衡过,只有第二次才是新证据。

    关闭理由:not_planned,同时摘掉 pm:on-hold。


    Generated by Claude Code

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions