Skip to content

docs(app-shell): the flow canvas draft node becomes a real notify node (objectui#8483) - #8855

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-8483-readme-flow-node-action
Sep 9, 2026
Merged

docs(app-shell): the flow canvas draft node becomes a real notify node (objectui#8483)#8855
os-zhuang merged 1 commit into
mainfrom
claude/issue-8483-readme-flow-node-action

Conversation

@claude

@claude claude Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Fixes #8483

What changed

One node in packages/app-shell/README.md's Visual flow canvas jsonc draft (was line 395):

-    { "id": "email", "type": "action", "label": "Send reminder" },
+    { "id": "email", "type": "notify", "label": "Send reminder",
+      "config": { "recipients": "{record.owner}", "title": "Renewal reminder" } },

action is not a flow node kind. It is absent from FlowNodeAction — the canonical built-in list in the objectstack sibling repo, packages/spec/src/automation/flow.zod.ts — and absent from the canvas's own 18-entry NODE_PALETTE. FlowNodeSchema.type is checked against the live action registry at registerFlow() time (flow.zod.ts:14-16), so a reader who copied this draft got the node refused, not silently ignored.

notify is not an "intent match" judgement call — it is what the published contract leaves standing:

  • script, the other candidate, disqualifies itself twice for this draft. Its config.function is REQUIRED ("a node naming no callable is flagged at build and refused at execute", flow.zod.ts:39-45) and the draft node carried no config at all — swapping one refusal for another is not a fix.
  • The same comment names the replacement itself: the retired email/slack dispatch branches say "use notify".

The premise that turned one word into three lines

The dispatch carried a premise to be measured rather than taken: notify has no required config key, so the draft node is complete once the word changes. Measured, and falsified. notify has required config too, in two places, both in packages/spec/src/automation/io-node-config.zod.ts (objectstack, read at 881ce2b):

what is required where it is declared
recipients io-node-config.zod.ts:186z.union([z.string(), z.array(z.string())]), no .optional(), unlike every other key on NotifyConfigSchema
one content source: title or template io-node-config.zod.ts:261 superRefine, message at :299"A notify node needs one content source ... Neither was given, so there is nothing to deliver."

And it bites a config-less node specifically: parseNodeConfig parses config ?? {} (service-automation/src/builtin/parse-config.ts:99), the notify executor runs it at execute time (builtin/notify-node.ts:250), and {} fails both checks. The descriptor's JSON-Schema configSchema deliberately carries no required array (notify-node.ts:168-175 says the execute-time guard owns enforcement), so registration passes and the refusal lands at execute — precisely the failure shape script was rejected for.

⇒ the draft gains exactly two keys, the minimal set that satisfies those two lines, and the jsonc block is not otherwise expanded.

The three readings (⛔ no gate is claimed to prove this)

check:doc-types' package-README leg is not switched on yet (objectui#7896, blocked behind objectui#8115), so CI is green either way. The deliverable is the change plus a measurement:

SUBJECT   grep -c '"type": "action"' packages/app-shell/README.md    ->  0
LIT CTRL  same probe, same jsonc block:  "type": "start"     -> 1
                                         "type": "decision"  -> 1
                                         "type": "end"       -> 1
                                         "type": "notify"    -> 1   (the value written)
THIRD     objectstack packages/spec/src/automation/flow.zod.ts:38
          'notify',  // Outbound notification (ADR-0012) - dispatched via the messaging service

The lit control is the point: the still-valid kinds survive the same probe, so the zero is a reading rather than a deleted block.

Why this site now needs NO DOC_TYPE_EXEMPTIONS entry

objectui#8115's acceptance gives each of the 25 census sites either a DOC_TYPE_EXEMPTIONS entry naming its vocabulary and declaration site, or a re-classification as a defect with a card. This card is that re-classification. Fixed, README.md:395 names a real flow node kind, so the site disappears from the 25 instead of becoming the 25th exemption — the table ends up one row shorter, not one row longer. The card's own reason for why that matters:

a false reason in DOC_TYPE_EXEMPTIONS is worse than a missing entry: the table's entire contract is that the next reader can re-check the ruling rather than take it.

⛔ No DOC_TYPE_EXEMPTIONS entry is written here — that surface is objectui#8115's, and this PR touches neither it nor scripts/check-doc-component-types.mjs.

Step-one reading (the card's written-in re-grading trigger), reported either way: the false reason had not landed in DOC_TYPE_EXEMPTIONS — it was still only a candidate row in PR #8111. Read fresh from scripts/check-doc-component-types.mjs on this branch: 32 file keys in the table, 0 of them under packages/ or naming app-shell, 0 occurrences of the string README anywhere in the table body; lit control content/docs/core/app-schema.mdx present in the same parse. ⇒ no p2 re-grade.

Clause-② declaration

Clause-②: no — docs only. The diff is one Markdown file in this repo; it touches no packages/spec/src/** contract schema, no error-code ledger, and widens no accepted set. It moves a teaching draft toward the published contract, so nothing new is accepted anywhere.

Contract-text: objectstack packages/spec/src/automation/flow.zod.ts:38'notify', // Outbound notification (ADR-0012) - dispatched via the messaging service; and packages/spec/src/automation/io-node-config.zod.ts:186recipients: z.union([z.string(), z.array(z.string())]), plus :299'A notify node needs one content source: inline title (+ optional message), or a template ...'. Both were already published and unchanged; the README now conforms to them.

Gates

gate exit verdict line
node scripts/check-governed-queue-guard.mjs --test packages/app-shell/README.md 0 NOT GOVERNED — 1 path(s) checked against 5 governed surface(s); none matched.
same, with AGENTS.md as lit control 3 GOVERNED — 1 of 2 path(s), listing only AGENTS.md ⇒ the probe is live and the diff path is genuinely ungoverned
node scripts/check-changeset-presence.mjs 0 No source or published contract of a released package changed in this range, so no changeset is owed. (measured: 1 file(s) changed, 0 of them published source) ⇒ no changeset
node scripts/check-control-bytes.mjs 0 OK (scanned 7045 tracked text file(s); skipped 85 binary).
node scripts/check-doc-component-types.mjs 0 Every documented component type is registered. (188 doc files, 893 type literals — this README is not in its scan set yet, see objectui#7896)
node scripts/check-doc-fence-languages.mjs 0 every TypeScript block in 227 document(s) is fenced ts/tsx/typescript
node scripts/check-readme-exports.mjs 1 NOT MEASURED — prerequisite not met, not a red gate: 543 lines of type entry ./dist/index.d.ts is not on disk -- run pnpm build first, across 43 package READMEs. Control leg: the identical run on a detached origin/main worktree (my change absent) gives the same exit 1 and the same 543 lines ⇒ diff-independent. CI builds first and judges it there.

No package source changed, so no build closure and no package test/typecheck is owed by this diff (the changeset gate's own count — 0 published source files — is that measurement).

验收备注 (out of scope, not repaired here)

Two further defects in the same jsonc block, both found while measuring the node above, both left untouched per this card's boundary (the card names one site). Filed together as objectui#8854 (unlabelled, unassigned — grading is the triage seat's), not ridden along:

  1. The decide node carries "ui": { "x": 220, "y": 180 } labelled "optional persisted canvas position", but flowNodeObject (flow.zod.ts:283) is a strictObject that declares position, not ui — and the README's own prose 12 lines below says so: "a draft that still carries ui fails client-side validation and is rejected on save with a 422". A reader who copies the block still gets a 422, now for a different key.
  2. All four edges omit id, which FlowEdgeSchema declares required (flow.zod.ts:562, id: z.string() with no .optional()).

Generated by Claude Code

The "Visual flow canvas" jsonc draft taught `{ "id": "email", "type":
"action", ... }`. `action` is not a flow node kind: it is absent from
`FlowNodeAction` (objectstack `packages/spec/src/automation/flow.zod.ts`,
20 members) and from the canvas's own 18-entry `NODE_PALETTE`, so a reader
copying the draft has the node refused when the type is checked against the
live action registry at `registerFlow()`.

`notify` is the replacement the spec itself names for the retired
`email`/`slack` dispatch branches (flow.zod.ts:38-45). `script`, the other
candidate, disqualifies itself: its `config.function` is REQUIRED, and this
draft node carries no `config` at all.

`notify` turns out to have required config too, so the one-word change alone
would have swapped one refusal for another: `NotifyConfigSchema` declares
`recipients` non-optional (io-node-config.zod.ts:186) and its superRefine
(:261, message at :299) refuses a node carrying neither `title` nor
`template`. The executor parses `node.config ?? {}` through that contract at
execute time (notify-node.ts:250, parse-config.ts:99), so a config-less
`notify` node is refused. The draft therefore gains exactly those two keys
and nothing else.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01611D6ZaRaMmwTNQmSbk8MH
@github-actions github-actions Bot added documentation Improvements or additions to documentation package: app-shell labels Sep 9, 2026
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 50 chunks) 3485.4 KB 3512.7 KB
Main entry chunk (gzip) 144.1 KB 350 KB
Entry file index-qV1osKj7.js
Status PASS

The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it.


📦 Bundle Size Report

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 16.69KB 6.21KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.06KB 3.86KB
auth (ActiveOrganizationStorage.js) 25.05KB 9.16KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.18KB 10.59KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.65KB 2.22KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.41KB 1.23KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.21KB 10.80KB
auth (createAuthenticatedFetch.js) 8.46KB 3.43KB
auth (index.js) 3.19KB 1.44KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 26.08KB 7.56KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 500.00KB 114.54KB
core (index.js) 7.48KB 2.96KB
create-plugin (index.js) 26.68KB 8.94KB
data-objectstack (index.js) 198.39KB 55.29KB
fields (index.js) 246.35KB 62.12KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 1.22KB 0.64KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 6.57KB 2.76KB
i18n (index.js) 3.65KB 1.47KB
i18n (pickLocalized.js) 7.62KB 3.26KB
i18n (provider.js) 26.89KB 9.04KB
i18n (useDisplayLocale.js) 2.85KB 1.45KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 38.84KB 10.94KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 2.53KB 0.85KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 4.39KB 1.66KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 13.52KB 4.88KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.24KB 2.16KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.39KB 3.10KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 14.81KB 3.63KB
plugin-calendar (index.js) 49.03KB 13.93KB
plugin-charts (index.js) 71.39KB 19.92KB
plugin-chatbot (index.js) 194.54KB 46.34KB
plugin-dashboard (index.js) 131.43KB 34.44KB
plugin-designer (index.js) 215.51KB 44.29KB
plugin-detail (index.js) 252.45KB 65.33KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 134.25KB 33.52KB
plugin-gantt (index.js) 167.16KB 40.99KB
plugin-grid (index.js) 210.67KB 57.19KB
plugin-kanban (index.js) 57.03KB 16.26KB
plugin-list (index.js) 112.73KB 27.69KB
plugin-map (index.js) 20.49KB 6.83KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 43.42KB 11.92KB
plugin-timeline (index.js) 30.10KB 8.74KB
plugin-tree (index.js) 9.55KB 3.32KB
plugin-view (index.js) 84.54KB 20.84KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.66KB 3.50KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 81.07KB 26.86KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.63KB 2.18KB
react (schema-input.js) 2.32KB 1.24KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 6.58KB 2.74KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 5.55KB 2.45KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 20.57KB 5.88KB
sdui-parser (provenance.js) 3.66KB 1.82KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 13.64KB 4.59KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 1.00KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 2.93KB 1.49KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 4.74KB 2.25KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 4.73KB 2.28KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 14.27KB 5.47KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.11KB 3.32KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

Copy link
Copy Markdown
Contributor

PM 复核 — 通过。已翻 ready,auto-merge 已武装。

PR 状态由本席翻转,你不要再写 draft 标志 —— 转草稿会静默杀死 auto-merge 与合并队列成员资格,GitHub 不会恢复。


⛔ 先记本席的错:裁决 ① 给了两条理由,只有一条成立

本席排除 script 时写了两条:

(a) 它的 config.functionREQUIRED,而 README 那个草稿节点一个 config 都没有 ⇒ 选 script 只是把一个"注册时被拒"的草稿换成一个"被拒"的草稿。换一种拒法不是修复。
(b) 规格自己点名 notify 作为那批已退休的 email/slack 派发的替代。

(a) 是死的。 你测了,本席也去 objectstack packages/spec/src/automation/io-node-config.zod.ts 复核:

:126  「`recipients` is **required at execute time** (the step fails without it)」
:296-302  superRefine:「A notify node needs one content source: inline `title` … or a `template`
           reference … Neither was given, so there is nothing to deliver.」

notify 同样要 config。 本席那句「换一种拒法不是修复」对两个候选都成立,所以它根本没有把 script 排除掉 —— 它只是描述了两者共同的处境。

裁决 ① 的结论是对的,但它只站在 (b) 上。 ⛔ 本席不让"两条排除"的说法留在记录里。

⭐ 为什么这条证伪不显然 —— 你给的机制,值得单独记

notify 的描述符 JSON-Schema configSchema(service-automation/src/builtin/notify-node.ts:168-175)刻意没有 required 数组,而 Zod 契约要求 recipients + 一个内容源。

一个无 config 的 notify 节点能过 registerFlow(),只在执行时被拒。 一次浅层的"注册能不能过"检查会回答"没问题"。

⇒ ⭐ 而这也让本席理由 (a) 的措辞双重不准:本席写的是 script "注册时被拒"、notify 没事;实际上两者都会被拒,只是拒在不同时刻。⛔ 把两种失败混成一种,正是本卡治的那类毛病换了个层面。


本席自测的读数(git 层,带亮对照)

head = de75b322e · 1 file · +2 / −1

"type": "action"   归零
改后的节点:
  { "id": "email", "type": "notify", "label": "Send reminder",
    "config": { "recipients": "{record.owner}", "title": "Renewal reminder" } },

⇒ 裁决 ① 走 notify;裁决 ② 的被证伪分支执行正确 —— 只补了最小的两个键,jsonc 块没有被顺手扩写。

STEP ONE 干净:DOC_TYPE_EXEMPTIONS 32 个文件键、packages/ 下 0 个、提到 README 的 0 个,且带亮对照(content/docs/core/app-schema.mdx 在同一次解析里出现)⇒ 那条假理由尚未落进豁免表 ⇒ 分诊席写死的 p2 重定级触发不发火,维持 p3。


⚠️⚠️ 这个 PR 去掉的是三个拒绝理由中的一个 —— ⛔ 不许写成"这段草稿修好了"

你自己立的 objectui#8854 说得很清楚,而本席在树上看见了它的主体就在改动的上一行:

{ "id": "decide", "type": "decision", "label": "Renew?",
  "ui": { "x": 220, "y": 180 } },   ← 已退休的位置键(strictObject 声明的是 position)
...
"edges": [ { "source": "start", "target": "decide" },    四条边全缺必填的 id

照抄这段草稿仍然会被拒,只是不再因为 type 被拒。 ⭐ 而 #8854 最锋利的一点是:README 自己往下 12 行的散文就写着那个 ui 键会被 422 拒绝 —— 页面自己反驳自己的示例。

⇒ 本 PR 的价值声称必须停在"移除了一个拒绝理由"上。⛔ 本席在落地评论里也会这么写。

⭐ 而你把它另立成卡而不是塞进本 PR,是对的:派发词写死了「⛔ 不动 README 里其它任何块」,而卡点名的是一个站点。⛔ 一个"顺手把整块修好"的 PR 会把三个不同性质的判断压成一次编辑。

其余核实项

  • 不写豁免条目 —— 遵守了。裁决 ③ 已写进 PR 正文:修好之后这个站点是真的 flow 节点种类,从 objectui#8115 的 25 项里消失,而不是变成第 25 条豁免。
  • 验收没有拿闸门当证据 —— 三条读数齐:主体归零、亮对照(start/decision/end/notify 各 1)、以及从兄弟仓源码读的第三条(flow.zod.ts:38'notify'),⛔ 不是凭记忆。
  • changeset 是量出来的:check-changeset-presence exit 0「0 of them published source」⇒ 不欠。
  • NOT MEASURED 被如实声明而不是当成红:check-readme-exports exit 1 是未构建的 dist,而你跑了对照腿 —— 同一命令在不动本改动的 origin/main worktree 上给出同样的 exit 1 与同样的 543 行 ⇒ 与本 diff 无关。⭐ 这条对照把"闸门坏了"和"我弄坏了闸门"分开了。
  • 治理面守卫带亮对照:该路径 exit 0,AGENTS.md exit 3。
  • ⛔ 未动 objectstack 兄弟仓任何文件(只读)。

席位意见 —— 你留白的那一行

席位意见。 本卡的价值是一次重新归类:PR #8111 的普查把这个站点记成「flow-graph node kind」,而它不是 —— NODE_PALETTE 18 种里没有 action,FlowNodeAction 枚举里也没有。而卡说得最准的一句是:一条理由错误的豁免条目,比一条缺失的条目更糟 —— 因为下一个复核者会把它核对通过。

⛔ 本席必须记下自己的错:裁决 ① 给了两条排除理由,只有 (b) 成立。(a) 说 notify 不像 script 那样要 config —— 实测两者都要,只是拒在不同时刻,而这一点被 notify 描述符里刻意缺席的 required 数组盖住了(能过注册、只在执行时拒)。实现方去验了而不是采信本席,并按被证伪的分支只补了最小两个键。

⚠️ 并且这个 PR 只移除了三个拒绝理由中的一个。另两个是实现方自己测出来并另立的 objectui#8854,其中一个的证据是这一页自己往下 12 行的散文。⛔ 谁都不要把本 PR 读成"那段草稿现在能用了"。

关卡:非条款② —— 纯文档,一个 jsonc 值加两个键;不触任何已发布包面。

落地后本席按内容核验(⛔ 不按 sha),带亮对照。


Generated by Claude Code

@os-zhuang
os-zhuang marked this pull request as ready for review September 9, 2026 14:39
@os-zhuang
os-zhuang added this pull request to the merge queue Sep 9, 2026
Merged via the queue into main with commit 0675618 Sep 9, 2026
32 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-8483-readme-flow-node-action branch September 9, 2026 15:02
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 package: app-shell

Projects

None yet

2 participants