Repository navigation
Commit 44a030b
fix(cli): os validate --target allows the ADR-0031 parallel / try_catch containers, and the restriction profile docblocks state the reader rules (#31277)
<!-- claude-projects-attribution: {"github_login":"os-project-manager"}
-->
_Requested by **Leehom** · [project
thread](https://claude.ai/code/project/chan_01TenzsRopZj4jMbvjX8uz1X?thread=cmsg_01TenzsRopZj4jMbvjX8uz1XAhN7jUu184vzuXHSCNx6Hb)_
Fixes #31239
Fixes #31264
Clause-②: yes (widening)
Metadata-protocol: none
## 维护者速读
- **改了什么**:`os validate --target` 读限制配置时,把引擎自带的 `parallel` / `try_catch`
容器节点当作结构节点(和 `start` / `end` 一样)一律放行,容器里面的每个节点照常按白名单判。spec 里
`allowedFlowNodeTypes` 与 `allowCode` 两段注释写明读者规则,其中 `allowCode` 一段写明
`devPlugins` 不按代码判(#31276 已让 `os build` 不再把它写进产物)。另有单元测试与一个 patch
changeset。
- **为什么改**:白名单只能写 `FlowNodeAction`
里的类型,而这两个容器不在其中,于是禁止代码的环境把它们当插件节点拒掉,而且任何配置都放行不了(#31239 第 1 项)。您已选定方案
C(#31354)。
- **风险与回滚**:只放宽一个本地校验命令,以前被拒的流程现在通过;不改任何 schema 形状或取值集合,不碰运行时。cloud 是否从
`manifest_json` 读 `devPlugins` 仍未测,见 Acceptance notes。回滚即 revert。
- **先看**:`packages/cli/src/utils/restriction-profile.ts` 的
`FLOW_CONTAINER_NODE_TYPES` 与 `judgeNodeType`
首行;`packages/spec/src/system/restriction-profile.zod.ts` 两段「Reader
rules」注释。
- **两分钟验证**:`pnpm --filter @objectstack/cli exec vitest run
--maxWorkers=2 src/utils/restriction-profile.test.ts`,预期 23
个全部通过,其中两条是本卡新增(容器放行、`loop` 仍按白名单判)。
- **需要你做的**:无,席位落地。
## What changes
1. **Item 1, option C.** Ruled C by the maintainer (decision card
#31354, comment 6717120942, 2026-11-08).
`packages/cli/src/utils/restriction-profile.ts`: reader rule 1 now
covers `FLOW_CONTAINER_NODE_TYPES`, derived from the published
`PARALLEL_NODE_TYPE` / `TRY_CATCH_NODE_TYPE` constants
(`@objectstack/spec/automation`). Those two containers are always
allowed, like `start` / `end`, and every node inside their regions is
still judged, because `collectFlowGraphs` walks into `branches[]`, `try`
and `catch`. `loop` (`LOOP_NODE_TYPE`) is already a `FlowNodeAction` id,
so `allowedFlowNodeTypes` keeps judging it like any built-in. No
vocabulary change: `allowedFlowNodeTypes` is still
`z.array(FlowNodeAction)`.
2. **Item 3.** `packages/spec/src/system/restriction-profile.zod.ts`,
JSDoc only (no `.describe()` text, no shape): the `allowedFlowNodeTypes`
docblock states the reader rules. `start` / `end` and the two containers
are structural and always allowed. A `script` node is also subject to
`allowCode`. A type outside the profile's vocabulary cannot be named by
the list, so `allowCode` governs it (ruling 6710350208); the docblock no
longer says such a type comes from a code plugin, since the vocabulary
is set to grow (#31344).
3. **Item 2, the spec half of the `devPlugins` work.** Before the first
round the thread measured that `os compile` wrote `devPlugins` into
`dist/objectstack.json` and `os package publish` snapshots that file
into `sys_package_version.manifest_json`, so the seat moved the
carve-out to the other card (claim amendment 6712791333). PR #31276
(merged as `ea053b4a`) made the artifact write delete `devPlugins`
beside `demoStaff` and added the reader's `NEVER_REACHES_TARGET`
carve-out. This branch merges `origin/main` (no rebase), keeps that
carve-out next to `FLOW_CONTAINER_NODE_TYPES` in the one conflict, and
writes the sentence #31276 left owed into the `allowCode` docblock:
`devPlugins` is not judged by `allowCode`, because only a local
development boot loads it and `os build` leaves it out of the artifact a
target installs, while `UNMANAGED_INSTALL_KEY_DISPOSITIONS` still
classifies it as `code` for an unmanaged install. Checked against the
merged tree: `compile.ts` deletes `finalBundle.devPlugins`, and the
table still reads `devPlugins: 'code'`.
4. `.changeset/restriction-profile-adr-0031-containers.md`:
`@objectstack/cli` and `@objectstack/spec` patch (the spec JSDoc ships
in its `.d.ts`), both declaration lines at the head of the body.
## Tests
`packages/cli/src/utils/restriction-profile.test.ts`, two new cases
under "the reader rules":
- `parallel / try_catch are always allowed`: a flow holding both
containers, with a `notify` node in a parallel branch, a `get_record` in
`try` and a `notify` in `catch`. Under `allowCode: false` and a list of
`['get_record']`, no row names a container and exactly the two `notify`
nodes are refused by `allowedFlowNodeTypes` at their region paths. With
`notify` added to the list, nothing is refused. The case also pins that
neither id is in `FLOW_BUILTIN_NODE_TYPES`.
- `loop is a FlowNodeAction id`: a `loop` not in the list is refused by
`allowedFlowNodeTypes`.
<details><summary>Ablation (one-off, not kept)</summary>
`node scripts/ablation-replace.mjs` on `restriction-profile.ts`,
replacing the rule-1 line with the pre-change `if
(FLOW_STRUCTURAL_NODE_TYPES.includes(type)) return undefined;` (anchor 1
→ 0, blob `dbc0daaabec5` → `2b0aa2d61236`): the container case fails
(`Tests 1 failed | 22 passed (23)`). Restored: blob equals HEAD
`dbc0daaabec5`, `git diff HEAD` empty. The CLI unit suite runs `src/`,
so no dist leg applies.
</details>
## Acceptance notes
- The order asked whether `loop` is already a `FlowNodeAction`: it is
(`flow.zod.ts`, `'loop', // For Each`), so only `parallel` and
`try_catch` needed the rule.
- Open residual, not measured: whether `objectstack-ai/cloud` reads
`devPlugins` out of `sys_package_version.manifest_json`. That repository
is not reachable from this session (as #31276 also recorded), and an
artifact built before #31276 still carries the key. The docblock speaks
for what `os build` writes now.
- The claim's line reads `Clause-②: yes`; this body and the changeset
write `yes (widening)`, the same value with the arm the order expects
(the profile now admits graphs it refused).
## Verification
Head `2a6b5bfe` adds one JSDoc-only commit on `e7693b99` (the ruled
wording of the outside-the-vocabulary rule): `pnpm --filter
@objectstack/spec run typecheck` exit 0,
`src/system/restriction-profile.test.ts` 27/27, cli
`src/utils/restriction-profile.test.ts` 24/24, `check:docs`,
`check:api-surface`, `check-changeset-no-major` and `check-nul-bytes`
exit 0.
Local, on the merged head `e7693b99` (merge of `origin/main` `59d9815a`,
which carries #31276, plus the docblock commit), after `pnpm --filter
'@objectstack/cli...' build`:
- `dispatch-gates --commands`: 83 derived, 81 exit 0, 2 NOT MEASURED
(`check:dual-build-cjs-loads` and `check:i18n-coverage`, both exit 3
PREREQUISITE NOT MET: they need every package's `dist`, CI's). `--ran`
reconciles 83 accounted, 0 unrun.
- `pnpm --filter @objectstack/spec test`: 821 files / 25964 tests passed
(1 todo). `pnpm --filter @objectstack/spec run typecheck` exit 0.
- `pnpm --filter @objectstack/cli exec vitest run --project unit`: 401
files / 5666 tests passed, #31276's reader case and these two container
cases together. `test/validate-target-restriction-profile.test.ts` and
`test/build-demo-staff-artifact.test.ts` (the door and the artifact
drop): 2 files / 11 tests passed. `pnpm --filter @objectstack/cli run
typecheck` exit 0.
- First round (head `405b3d48`): `check:generated` 13 of 14 current,
`test-typecheck-debt.json` stale only from `tsc` dying under the default
heap; `check:test-typecheck` with a 4 GB heap OK, nothing regenerated.
CI runs the full set.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01FEkQ5kxRsYPLNnBt5AWYj1)_
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01FEkQ5kxRsYPLNnBt5AWYj1
<!-- signed: domain:spec#1 · os-project-manager ·
session_01FEkQ5mw7HFYn9o4LEGMQdK -->
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent eff90af commit 44a030b
4 files changed
Lines changed: 105 additions & 4 deletions
File tree
- .changeset
- packages
- cli/src/utils
- spec/src/system
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
14 | | - | |
| 14 | + | |
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
| |||
142 | 142 | | |
143 | 143 | | |
144 | 144 | | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
145 | 185 | | |
146 | 186 | | |
147 | 187 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
43 | 43 | | |
44 | 44 | | |
45 | 45 | | |
46 | | - | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
47 | 53 | | |
48 | 54 | | |
49 | 55 | | |
| |||
59 | 65 | | |
60 | 66 | | |
61 | 67 | | |
| 68 | + | |
| 69 | + | |
62 | 70 | | |
63 | 71 | | |
64 | 72 | | |
| |||
150 | 158 | | |
151 | 159 | | |
152 | 160 | | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
153 | 169 | | |
154 | 170 | | |
155 | 171 | | |
| |||
300 | 316 | | |
301 | 317 | | |
302 | 318 | | |
303 | | - | |
304 | | - | |
| 319 | + | |
| 320 | + | |
305 | 321 | | |
306 | 322 | | |
307 | 323 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
66 | 66 | | |
67 | 67 | | |
68 | 68 | | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
69 | 81 | | |
70 | 82 | | |
71 | 83 | | |
| |||
91 | 103 | | |
92 | 104 | | |
93 | 105 | | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
94 | 126 | | |
95 | 127 | | |
96 | 128 | | |
| |||
0 commit comments