Repository navigation
Commit 218f834
fix(app-shell): clearing the flow designer's cron no longer leaves a schedule block with no cadence (#31412)
<!-- claude-projects-attribution: {"github_login":"os-project-manager"}
-->
_Requested by **Leehom** · [project
thread](https://claude.ai/code/project/chan_01TenzsRopZj4jMbvjX8uz1X?thread=cmsg_01TenzsRopZj4jMbvjX8uz1XSU6NATZRao9u3ah6yKg179)_
Fixes #31383
Clause-②: no
Metadata-protocol: none
## 维护者速读
- 改了什么:流程设计器开始节点的「Cron schedule」输入框被清空时,如果剩下的 `config.schedule`
已经没有任何周期(只剩 `type`、`timezone` 之类),现在整块删掉,不再写出 `{ type: 'cron' }` 或 `{
type: 'cron', timezone }`。无类型的 `{ expression, timezone }` 清空后原来会剩 `{
timezone }`,同一个缺陷,一并处理。输入新的 cron 时行为不变:带类型的块照旧保留 `type` 和 `timezone`。
- 为什么改:留下的无周期块引擎读不出调度,定时流程静默不绑定,时间相对扫描也不会按帮助文字说的「留空默认每天」处理;PR #31376
落地后,同样的草稿保存会被 `FlowSchema` 以 422 拒绝,而这个形状正是设计器自己写出来的。
- 风险与回滚:只改 `@object-ui/app-shell` 里 `scheduleWithExpression`
一个函数的「清空」分支;不改 spec、不改服务端、不加 i18n 文案。回滚即 revert。
-
先看:`ui/packages/app-shell/src/views/metadata-admin/inspectors/flow-node-config.ts`
中 `scheduleWithExpression` 的清空分支(`return normalizeScheduleCadence(next)
=== null ? undefined : next;`),以及两个测试文件末尾新增的 `objectstack#31383`
describe。
- 两分钟验证:`pnpm --dir ui exec vitest run
packages/app-shell/src/views/metadata-admin/inspectors/flow-node-config.scheduleCadence-12779.test.ts
packages/app-shell/src/views/metadata-admin/inspectors/FlowNodeInspector.scheduleCadence-12779.test.tsx`,预期
2 个文件 68 个用例全绿。
- 需要你做的:无,席位落地。
## What changes
- **`scheduleWithExpression`** (`flow-node-config.ts`,
`@object-ui/app-shell`). The clearing arm used to delete `expression`
and `cron` and keep whatever else the object held, collapsing only an
object left empty. It now returns `undefined` whenever the remaining
object resolves to no cadence through `normalizeScheduleCadence`, the
designer's branch-for-branch mirror of the engine's `normalizeSchedule`.
So:
- a cleared `{ type: 'cron', expression }` or `{ type: 'cron',
expression, timezone }` stores no `config.schedule`;
- a cleared untyped `{ expression, timezone }` stores no
`config.schedule` either (it used to leave `{ timezone }`);
- an untyped `{ expression }` stores nothing, as before;
- a key the cron stood in front of and that still binds is kept:
clearing `{ expression, intervalMs }` leaves `{ intervalMs }`, which the
engine binds as an interval, as before.
The set arm is unchanged. Its tail is rewritten without the `else`,
because the set arm always writes `expression`, so the old empty-object
check could only fire on the clearing arm. The function's doc comment
and the field's comment say what clearing now stores.
- **Other designer write paths.** None writes `config.schedule`.
`FlowNodeInspector.tsx` routes every commit on the Cron schedule path
through `scheduleWithExpression` (line 552); the other `schedule*`
helpers in the file (`normalizeScheduleCadence`, `scheduleCadenceOf`,
`scheduleFieldValue`, `readOnlyScheduleCadence`) only read. The Advanced
JSON box writes whatever the author types and is not a designer-produced
shape.
- **Changeset**
`.changeset/31383-flow-designer-cleared-cron-drops-typed-schedule.md`:
`@object-ui/app-shell` patch, both declaration lines.
## Tests
- `flow-node-config.scheduleCadence-12779.test.ts`: the old assertion
that pinned the defect (clearing `{ type: 'cron', expression, timezone:
'UTC' }` returned `{ type: 'cron', timezone: 'UTC' }`) is removed from
the existing clearing case, and a new describe for objectstack#31383
adds 11 cases:
- clearing a typed cron, a typed cron with a timezone, a typed cron
cleared to `undefined`, a typed `{ cron }` with a timezone, a typed cron
that already had no cadence, an `interval` type that carried only an
expression, and an unknown type beside an expression: each returns
`undefined`;
- clearing an untyped `{ expression, timezone }` returns `undefined`;
- CONTROLS: an untyped `{ expression }` still clears to `undefined`; a
cron typed over `{ type: 'cron', expression, timezone }` or `{ type:
'cron', timezone }` keeps `type` and `timezone`; clearing `{ expression,
intervalMs }` keeps the interval the engine then binds.
- `FlowNodeInspector.scheduleCadence-12779.test.tsx` (rendered, through
the real Cron schedule input and `fireEvent.change`): clearing the box
on a typed cron, and on a typed cron with a timezone, leaves the start
node's `config` with no `schedule` key and its `objectName` kept, and
the box reads empty. CONTROL: clearing an untyped `{ expression }`
stores no schedule, as before. The file now imports `@objectstack/lint`
at module top, as its sibling inspector tests do, because the inspector
reaches it through function-body `import()`s and
`check:test-source-alias` asks an edited test file to pay that load at
collection.
- Ablation through `scripts/ablation-replace.mjs`: the clearing arm's
return put back to the old `Object.keys(next).length === 0 ? undefined :
next` (anchor 1 to 0, blob `aa3d830d` to `91bc6d94`). Result: 10 failed,
58 passed (68): the 8 new table cases and the 2 rendered typed cases
red; every CONTROL green. Restored: blob equal to HEAD (`aa3d830d`),
`git diff HEAD` empty. Both tests import `flow-node-config.ts` from
source by relative path, so no build sat between the mutation and the
run.
## Acceptance notes
- **The untyped `{ timezone }` leftover is fixed in place.** The grade
record says the untyped form already collapses; that holds for `{
expression }` but not for `{ expression, timezone }`, which left `{
timezone }`. The engine binds nothing from it, and PR #31376's
`flowStartScheduleReadsNothing` refuses an untyped object it reads
nothing from, so it is the same defect in the same function. All four
conditions of the bounded in-place fix hold: same defect class, a
mechanical fix pinned here, the file is inside this claim's surface, and
no new gate family. Named here so the seat can rule it out if it prefers
the narrower reading.
- **PR #31376 has not merged** (open, draft, at the time of this PR), so
the cleared case was not run through its `FlowSchema` refusals. The
shapes this PR stops writing are the ones its review named: a typed cron
with no `expression`, which the published `ScheduleSchema` already
refuses on `main`.
- **Declaration lines measured on the diff:** no published key, export,
schema arm or i18n string is added or removed. `Clause-②: no`,
`Metadata-protocol: none`, as the claim opened.
## Verification
Run on head `3251f97c` (base `origin/main` `03533d2c`).
<details><summary>Build, tests and lint</summary>
- Build under the verify lock: `pnpm --workspace-concurrency=2 --filter
'@objectstack/spec...' --filter '@objectstack/formula...' --filter
'@objectstack/client...' --filter '@objectstack/lint...' --filter
'@objectstack/sdui-parser...' build`: VERDICT command-exit 0.
- `pnpm --dir ui exec vitest run --maxWorkers=2` on the two touched test
files: Test Files 2 passed (2), Tests 68 passed (68).
- Every inspector test that imports `scheduleWithExpression`'s module or
renders `FlowNodeInspector` (`inspectors/FlowNodeInspector*` and
`inspectors/flow-node-config*`, 39 files): Test Files 39 passed (39),
Tests 667 passed, 1 skipped.
- eslint on the three changed source and test files: exit 0. `pnpm --dir
ui run check:new-line-citations`: 0 new citations, exit 0.
- `@object-ui/app-shell` `type-check` was not run locally (it needs
every `@object-ui/*` dist built); `check:type-check-debt` below exits 0,
and CI's type-check lane runs the package.
</details>
<details><summary>Derived gates (36)</summary>
`node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` derived 36 families on this diff. On head
`3251f97c` all 36 exited 0, among them `pnpm --dir ui exec vitest run
scripts/` and `pnpm check:type-check-debt`. `--ran` reconciliation with
exit codes recorded: 36 derived, 36 run, 0 NOT-MEASURED, 0 UNRUN. The
first round, on `93b35e72`, had one red: `check:test-source-alias` asked
the edited rendered test to load `@objectstack/lint` at module top;
`3251f97c` adds that import, and the whole list was re-run. Changed
lines: 106, under the 3,000 threshold.
</details>
---
_Generated by [Claude
Code](https://claude.ai/code/session_01FEkQ5oAnL2z711MLVm7ZnB)_
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01FEkQ5oAnL2z711MLVm7ZnB
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 1f029a7 commit 218f834
4 files changed
Lines changed: 98 additions & 8 deletions
File tree
- .changeset
- ui/packages/app-shell/src/views/metadata-admin/inspectors
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
31 | 35 | | |
32 | 36 | | |
33 | 37 | | |
| |||
238 | 242 | | |
239 | 243 | | |
240 | 244 | | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
241 | 269 | | |
242 | 270 | | |
243 | 271 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
171 | 171 | | |
172 | 172 | | |
173 | 173 | | |
174 | | - | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
175 | 220 | | |
| 221 | + | |
176 | 222 | | |
177 | 223 | | |
178 | 224 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
526 | 526 | | |
527 | 527 | | |
528 | 528 | | |
529 | | - | |
| 529 | + | |
| 530 | + | |
530 | 531 | | |
531 | 532 | | |
532 | 533 | | |
| |||
1705 | 1706 | | |
1706 | 1707 | | |
1707 | 1708 | | |
1708 | | - | |
| 1709 | + | |
| 1710 | + | |
| 1711 | + | |
| 1712 | + | |
| 1713 | + | |
| 1714 | + | |
1709 | 1715 | | |
1710 | 1716 | | |
1711 | 1717 | | |
| |||
1717 | 1723 | | |
1718 | 1724 | | |
1719 | 1725 | | |
1720 | | - | |
1721 | | - | |
1722 | | - | |
1723 | | - | |
| 1726 | + | |
1724 | 1727 | | |
1725 | | - | |
| 1728 | + | |
| 1729 | + | |
| 1730 | + | |
| 1731 | + | |
1726 | 1732 | | |
1727 | 1733 | | |
1728 | 1734 | | |
| |||
0 commit comments