Skip to content

Commit 69527a3

Browse files
chore: version packages (rc)
1 parent 2382580 commit 69527a3

153 files changed

Lines changed: 12014 additions & 83 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.changeset/pre.json

Lines changed: 105 additions & 1 deletion
Large diffs are not rendered by default.

examples/app-crm/CHANGELOG.md

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,168 @@
11
# @objectstack/example-crm
22

3+
## 4.0.92-rc.2
4+
5+
### Patch Changes
6+
7+
- 5293114: fix(automation): a decision's three declared ways to route a branch are now one working model (#4414)
8+
9+
A `decision` node advertised three mechanisms for splitting a path and only one
10+
of them did anything. The other two were the ADR-0049 `declared ≠ enforced`
11+
shape, and the pair of them shipped a guard that does not guard in
12+
`examples/app-crm`.
13+
14+
| mechanism | before | now |
15+
| :--------------------------------------------------- | :----------------------------------------------------------------------------------------------------- | :---------------------------------------------------- |
16+
| `edge.condition` | ✅ the only one that worked | unchanged |
17+
| `edge.isDefault` | **zero readers** anywhere but the schema declaration | BPMN default flow, enforced in `traverseNext` |
18+
| `decision.config.conditions[].label``branchLabel` | matched **0** out-edge labels across every example app, then fell back to the full edge set in silence | routes; an unclaimable label is logged, not swallowed |
19+
20+
## What was broken, end to end
21+
22+
`crm_convert_lead_wizard` means "already converted → abort screen; otherwise →
23+
the wizard". It ran **both**: an already-converted lead got
24+
"This lead has already been converted" and then walked straight into the
25+
conversion wizard behind it. Four independent silences stacked up:
26+
27+
1. the decision's first condition was authored `{lead_record.status} ==
28+
'converted'` — braces in a slot declared bare CEL, so it was string-compared
29+
and never true;
30+
2. the second (`'true'`) therefore won, yielding `branchLabel: 'No — proceed'`;
31+
3. no out-edge carried that label (they were `'Yes'` / `'No'`), so traversal
32+
discarded the branch and considered every out-edge;
33+
4. `e3b` was unconditional, so it ran regardless — and the natural fix, marking
34+
it `isDefault: true`, was a dead key.
35+
36+
## The model
37+
38+
`branchLabel` narrows the edge set → `condition` gates each edge → `isDefault`
39+
catches whatever is left. Concretely:
40+
41+
- **`isDefault` is enforced.** A default edge is traversed only when no
42+
conditional sibling of the same source node matched, and it is no longer part
43+
of the unconditional parallel fan-out — that distinction is the whole point of
44+
the marker. Passed over because a real branch won, its target records the same
45+
`skipped` step a closed gate does (#4354).
46+
- **An unclaimable branch label warns.** Traversal still falls back to the full
47+
edge set (a run mid-flight must not die on a metadata error) but says so,
48+
naming the computed branch and the out-edge labels that exist.
49+
- **A decision that declares no `conditions` reports no branch.** It used to
50+
report `'default'` unconditionally — a label no out-edge in the repo ever
51+
carried — which is why every decision node fell back to the full edge set.
52+
The `'default'` sentinel survives for the case it actually describes (declared
53+
conditions, none matched) and is now claimed by the `isDefault` edge as well
54+
as by an edge literally labelled `'default'`.
55+
- **`conditions[].expression` is evaluated as the bare CEL it is declared to
56+
be.** The raw string went to the legacy `{var}` template path, where
57+
`lead.status == 'converted'` cannot resolve and the branch is decided by
58+
string comparison. Unlike `edge.condition` this slot carries no
59+
`ExpressionInput` envelope — the decision descriptor is deliberately
60+
schemaless — so the executor supplies the dialect. A brace-in-CEL predicate
61+
now fails loudly (ADR-0032 §1c) instead of deciding `false`.
62+
63+
## Caught at authoring time too
64+
65+
Four new `os build` / `os validate` warnings, because a wrong route is silent at
66+
run time by nature (Prime Directive #12):
67+
68+
`flow-branch-label-unmatched` (the shipped shape),
69+
`flow-decision-unconditional-branch` (a guarded decision with an unconditional
70+
sibling — the actual hole), `flow-default-edge-with-condition` and
71+
`flow-multiple-default-edges`.
72+
73+
Both of the first two fire on the pre-fix `convert-lead.flow.ts` and are silent
74+
after it.
75+
76+
## Effect on flows that already exist
77+
78+
Enforcing `isDefault` changes how a **stored** flow behaves, and the flows it
79+
changes are mostly Studio's own. `objectui`'s flow edge inspector has always
80+
written `isDefault: true` when you bind an out-edge to a decision's default/else
81+
branch — into a key with zero readers, so that edge ran unconditionally, in
82+
parallel with whichever branch actually matched. Those flows now take exactly
83+
one branch. That is the fix, but it is a behaviour change on existing data
84+
rather than only on newly authored metadata, so it is worth knowing before
85+
upgrading: a flow that quietly ran two paths will now run one.
86+
87+
Nothing changes for an edge that never carried the marker — `isDefault` defaults
88+
to `false`, and an ordinary unconditional out-edge still fans out in parallel
89+
exactly as before.
90+
91+
## The example app
92+
93+
`crm_convert_lead_wizard`'s guard is now a plain exclusive gateway: the
94+
redundant `config.conditions` is gone and `e3b` carries `isDefault: true`. One
95+
mechanism per decision, and exactly one branch runs.
96+
97+
Verified: 11 new engine/executor tests (including the reported repro in both
98+
directions), 12 new linter tests; `@objectstack/service-automation` 577 tests
99+
and `@objectstack/cli` 652 tests green, all three example apps build with no new
100+
findings.
101+
102+
- Updated dependencies [80334c7]
103+
- Updated dependencies [a7163ea]
104+
- Updated dependencies [e6e9379]
105+
- Updated dependencies [e6b1b69]
106+
- Updated dependencies [2826d1e]
107+
- Updated dependencies [5a84d41]
108+
- Updated dependencies [20b1a9e]
109+
- Updated dependencies [4820f55]
110+
- Updated dependencies [462d9c4]
111+
- Updated dependencies [5b843fb]
112+
- Updated dependencies [b4487aa]
113+
- Updated dependencies [67bf2e2]
114+
- Updated dependencies [6117f7b]
115+
- Updated dependencies [cdf4d9a]
116+
- Updated dependencies [63b33e6]
117+
- Updated dependencies [9ca2d85]
118+
- Updated dependencies [a52e2ef]
119+
- Updated dependencies [5293114]
120+
- Updated dependencies [ff17642]
121+
- Updated dependencies [20bc357]
122+
- Updated dependencies [2382580]
123+
- Updated dependencies [3c7bcc0]
124+
- Updated dependencies [4b6cac7]
125+
- Updated dependencies [7631964]
126+
- Updated dependencies [ac471a0]
127+
- Updated dependencies [60ae58e]
128+
- Updated dependencies [ce92674]
129+
- Updated dependencies [07a4e26]
130+
- Updated dependencies [ec975f1]
131+
- Updated dependencies [eb4204b]
132+
- Updated dependencies [4f13be2]
133+
- Updated dependencies [ce92674]
134+
- Updated dependencies [cf2c9b7]
135+
- Updated dependencies [0f9faa2]
136+
- Updated dependencies [7cf42fe]
137+
- Updated dependencies [8aacf94]
138+
- Updated dependencies [a2cd18a]
139+
- Updated dependencies [4638aaa]
140+
- Updated dependencies [0222d3c]
141+
- Updated dependencies [7bba90b]
142+
- Updated dependencies [061406d]
143+
- Updated dependencies [9c93465]
144+
- Updated dependencies [ebb209c]
145+
- Updated dependencies [63b33e6]
146+
- Updated dependencies [2a44c1d]
147+
- Updated dependencies [f3141d8]
148+
- Updated dependencies [5a84d41]
149+
- Updated dependencies [fd3013a]
150+
- Updated dependencies [e5e7ee0]
151+
- Updated dependencies [800bdb0]
152+
- Updated dependencies [04f1182]
153+
- Updated dependencies [38f7e4f]
154+
- Updated dependencies [c57f3cf]
155+
- Updated dependencies [97faca3]
156+
- Updated dependencies [ad5fe25]
157+
- Updated dependencies [ea90179]
158+
- Updated dependencies [ce92674]
159+
- Updated dependencies [5ef0b5b]
160+
- Updated dependencies [48fbacb]
161+
- Updated dependencies [355e951]
162+
- Updated dependencies [dadb43f]
163+
- @objectstack/spec@17.0.0-rc.2
164+
- @objectstack/runtime@17.0.0-rc.2
165+
3166
## 4.0.92-rc.1
4167

5168
### Patch Changes

examples/app-crm/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@objectstack/example-crm",
3-
"version": "4.0.92-rc.1",
3+
"version": "4.0.92-rc.2",
44
"description": "Minimal CRM example — a smoke-test workspace that exercises the metadata loading pipeline (objects → views → app → dashboard → hook → flow → seed). For a full-featured enterprise CRM see https://github.com/objectstack-ai/hotcrm.",
55
"license": "Apache-2.0",
66
"private": true,

examples/app-showcase/CHANGELOG.md

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,136 @@
11
# @objectstack/example-showcase
22

3+
## 0.3.14-rc.2
4+
5+
### Patch Changes
6+
7+
- d449b0c: fix(cli): gate the two decision-routing shapes that can never work, and flag the inert `config.condition` (#4414)
8+
9+
Two follow-ups to #4440, both about metadata that reads like a guard and is not
10+
one.
11+
12+
## Two rules promoted to `error`
13+
14+
`flow-branch-label-unmatched` and `flow-default-edge-with-condition` now FAIL the
15+
build instead of warning. The bar for that — restated at the top of
16+
`lint-flow-patterns.ts`, because the old one no longer described the set — is
17+
**no reading of the author's metadata does what it says, deterministically, on
18+
every run**. Both qualify: a branch label no out-edge carries cannot route, and
19+
an edge that is both `isDefault` and conditional always lets the condition win,
20+
so the marker routes nothing. Neither _fails_; both are wrong every time and
21+
silently, which is worse.
22+
23+
The other two stay advisory on purpose, and the policy now says why:
24+
`flow-decision-unconditional-branch` is usually a guard that does not guard, but
25+
one guarded plus one unconditional out-edge is also a legal "maybe notify,
26+
always continue" fan-out, and `flow-multiple-default-edges` can genuinely mean
27+
"when nothing matched, do both". The bar is about _provability_, not severity of
28+
consequence — failing a customer's build on a shape we cannot prove wrong is the
29+
worse trade.
30+
31+
No wiring change was needed: `lintFlowPatterns` is already registered as
32+
`tier: 'gating'` across all three commands (#4409), which is exactly the seam
33+
`authoring-rule-wiring.test.ts` exists to guard.
34+
35+
## New rule: `flow-inert-node-condition`
36+
37+
`config.condition` is the trigger gate on a `start` node and is read by **no
38+
other node type** — the engine parse-validates it everywhere (so a malformed one
39+
is caught) and then ignores it. On a `decision` the name makes it read as the
40+
branch predicate, which is exactly how it got authored.
41+
42+
Three of the three bundled apps had one. `app-todo`'s `check_recurring` and
43+
`app-showcase`'s `needs_exec` both carried a predicate their out-edges were
44+
already enforcing — a third copy doing nothing. The showcase even had a comment
45+
next to it saying the node condition "is not evaluated by the engine", and kept
46+
it anyway; that is the residue this rule exists to stop accumulating. Both are
47+
now plain exclusive gateways.
48+
49+
Advisory, not gating: the surrounding edges usually still route correctly, so
50+
this is dead weight rather than a provable misroute. The node-type list is a
51+
closed set of builtins we have actually read, not "everything that isn't
52+
`start`" — ADR-0018 keeps `node.type` open and a plugin executor may legitimately
53+
declare and read its own `config.condition`.
54+
55+
## Studio
56+
57+
`objectstack-ai/objectui` carries the matching help-text fixes: the branch editor
58+
said a `true` branch **is** the default/else path (it is how you _ask_ for one —
59+
the marker goes on the out-edge), and the legacy single `Condition` field said
60+
"prefer Branches above", which reads as "this works, but the other is better".
61+
It does not work at all.
62+
63+
- Updated dependencies [80334c7]
64+
- Updated dependencies [a7163ea]
65+
- Updated dependencies [e6e9379]
66+
- Updated dependencies [e6b1b69]
67+
- Updated dependencies [2826d1e]
68+
- Updated dependencies [5a84d41]
69+
- Updated dependencies [20b1a9e]
70+
- Updated dependencies [4820f55]
71+
- Updated dependencies [462d9c4]
72+
- Updated dependencies [5b843fb]
73+
- Updated dependencies [b4487aa]
74+
- Updated dependencies [67bf2e2]
75+
- Updated dependencies [6117f7b]
76+
- Updated dependencies [cdf4d9a]
77+
- Updated dependencies [63b33e6]
78+
- Updated dependencies [9ca2d85]
79+
- Updated dependencies [a52e2ef]
80+
- Updated dependencies [5293114]
81+
- Updated dependencies [ff17642]
82+
- Updated dependencies [20bc357]
83+
- Updated dependencies [2382580]
84+
- Updated dependencies [3c7bcc0]
85+
- Updated dependencies [4b6cac7]
86+
- Updated dependencies [7631964]
87+
- Updated dependencies [ac471a0]
88+
- Updated dependencies [60ae58e]
89+
- Updated dependencies [ce92674]
90+
- Updated dependencies [07a4e26]
91+
- Updated dependencies [ec975f1]
92+
- Updated dependencies [eb4204b]
93+
- Updated dependencies [4f13be2]
94+
- Updated dependencies [ce92674]
95+
- Updated dependencies [cf2c9b7]
96+
- Updated dependencies [0f9faa2]
97+
- Updated dependencies [7cf42fe]
98+
- Updated dependencies [8aacf94]
99+
- Updated dependencies [a2cd18a]
100+
- Updated dependencies [4638aaa]
101+
- Updated dependencies [0222d3c]
102+
- Updated dependencies [7bba90b]
103+
- Updated dependencies [061406d]
104+
- Updated dependencies [9c93465]
105+
- Updated dependencies [ebb209c]
106+
- Updated dependencies [63b33e6]
107+
- Updated dependencies [2a44c1d]
108+
- Updated dependencies [f3141d8]
109+
- Updated dependencies [5a84d41]
110+
- Updated dependencies [fd3013a]
111+
- Updated dependencies [e5e7ee0]
112+
- Updated dependencies [800bdb0]
113+
- Updated dependencies [04f1182]
114+
- Updated dependencies [38f7e4f]
115+
- Updated dependencies [c57f3cf]
116+
- Updated dependencies [97faca3]
117+
- Updated dependencies [ad5fe25]
118+
- Updated dependencies [ea90179]
119+
- Updated dependencies [ce92674]
120+
- Updated dependencies [5ef0b5b]
121+
- Updated dependencies [48fbacb]
122+
- Updated dependencies [355e951]
123+
- Updated dependencies [dadb43f]
124+
- @objectstack/spec@17.0.0-rc.2
125+
- @objectstack/runtime@17.0.0-rc.2
126+
- @objectstack/service-datasource@17.0.0-rc.2
127+
- @objectstack/driver-sql@17.0.0-rc.2
128+
- @objectstack/cloud-connection@17.0.0-rc.2
129+
- @objectstack/connector-mcp@17.0.0-rc.2
130+
- @objectstack/connector-openapi@17.0.0-rc.2
131+
- @objectstack/connector-rest@17.0.0-rc.2
132+
- @objectstack/connector-slack@17.0.0-rc.2
133+
3134
## 0.3.14-rc.1
4135

5136
### Patch Changes

examples/app-showcase/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@objectstack/example-showcase",
3-
"version": "0.3.14-rc.1",
3+
"version": "0.3.14-rc.2",
44
"description": "Kitchen-sink showcase workspace — exercises every metadata type, every view type, every chart type, and the major end-to-end capability chains (security, automation, analytics). Built for demonstration, debugging, and coverage-driven verification.",
55
"license": "Apache-2.0",
66
"private": true,

0 commit comments

Comments
 (0)