@controllerai/cli 0.2.9 → 0.2.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/client.js +20 -5
- package/dist/api/client.js.map +1 -1
- package/dist/argv.js +330 -29
- package/dist/argv.js.map +1 -1
- package/dist/commands/agent.js +208 -8
- package/dist/commands/agent.js.map +1 -1
- package/dist/commands/auth.js +21 -5
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/doctor.js +63 -4
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/exec.js +161 -49
- package/dist/commands/exec.js.map +1 -1
- package/dist/commands/expr.js +284 -53
- package/dist/commands/expr.js.map +1 -1
- package/dist/commands/flow.js +58 -14
- package/dist/commands/flow.js.map +1 -1
- package/dist/commands/node.js +746 -173
- package/dist/commands/node.js.map +1 -1
- package/dist/commands/organize.js +1 -1
- package/dist/commands/organize.js.map +1 -1
- package/dist/commands/run.js +165 -33
- package/dist/commands/run.js.map +1 -1
- package/dist/commands/schema.js +8 -7
- package/dist/commands/schema.js.map +1 -1
- package/dist/commands/workflow.js +151 -24
- package/dist/commands/workflow.js.map +1 -1
- package/dist/config.js +152 -6
- package/dist/config.js.map +1 -1
- package/dist/context.js +66 -5
- package/dist/context.js.map +1 -1
- package/dist/index.js +11 -1
- package/dist/index.js.map +1 -1
- package/dist/nodeProps.js +333 -10
- package/dist/nodeProps.js.map +1 -1
- package/dist/output.js +6 -1
- package/dist/output.js.map +1 -1
- package/package.json +1 -1
- package/skills/controllerai-agents/SKILL.md +27 -9
- package/skills/controllerai-agents/references/instructions-and-versioning.md +1 -1
- package/skills/controllerai-data/SKILL.md +17 -0
- package/skills/controllerai-data/references/data-rails.md +1 -1
- package/skills/controllerai-expressions/SKILL.md +7 -3
- package/skills/controllerai-flow-control/SKILL.md +2 -0
- package/skills/controllerai-node-config/SKILL.md +33 -6
- package/skills/controllerai-node-config/references/prop-and-readiness.md +34 -0
- package/skills/controllerai-runs/SKILL.md +14 -4
- package/skills/controllerai-runs/references/debugging.md +1 -1
- package/skills/controllerai-start/SKILL.md +1 -0
- package/skills/controllerai-workflows/SKILL.md +13 -8
- package/skills/controllerai-workflows/references/command-map.md +3 -2
- package/skills/manifest.json +58 -58
|
@@ -95,6 +95,23 @@ Use `--env live` only when the user intends to inspect or mutate production stat
|
|
|
95
95
|
|
|
96
96
|
`data query --query` is plain-text search over serialized records and metadata, not a field predicate. Perform exact field filtering inside workflow expressions or inspect results explicitly.
|
|
97
97
|
|
|
98
|
+
## Delete records explicitly
|
|
99
|
+
|
|
100
|
+
Record deletion is CLI/REST-only; no workflow data node exposes it. Delete one known record or an explicit set of IDs:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
cai data delete <recordId> --type custom.customer --env dev --json
|
|
104
|
+
cai data delete-many --type custom.customer --records <id1,id2> --env dev --json
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Delete every record in a collection only with explicit user intent; `--all` also requires `--yes`:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
cai data delete-many --type custom.customer --all --yes --env dev --json
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
The default rail is development. Use `--env live` only for an intentional production deletion, then query that same rail to verify the result.
|
|
114
|
+
|
|
98
115
|
## Import and promote
|
|
99
116
|
|
|
100
117
|
Validate CSV before writing:
|
|
@@ -25,7 +25,7 @@ Field IDs are contracts. Prefer keeping an ID stable and changing only its displ
|
|
|
25
25
|
## Destructive operations
|
|
26
26
|
|
|
27
27
|
- `data delete` soft-deletes one record.
|
|
28
|
-
- `data delete-many --all` is broad and
|
|
28
|
+
- `data delete-many --all --yes` is broad, REST-backed, and DEVELOPMENT-ONLY — `--env live` is refused (`DEV_ONLY_ROUTE`). The only live write paths are single-record `data create/update/delete --env live` and `copy-to-live`.
|
|
29
29
|
- `schema delete` removes access to the whole collection and breaks its type references.
|
|
30
30
|
- CSV `--mode commit` appends rows.
|
|
31
31
|
- `copy-to-live` changes production data.
|
|
@@ -46,6 +46,8 @@ Copy binding and field names exactly. Important sources include:
|
|
|
46
46
|
|
|
47
47
|
Do not derive a binding from a display label. Context flags duplicate display names and supplies the de-duplicated JS name, input ID, and source node.
|
|
48
48
|
|
|
49
|
+
When compilation reports an unknown field, copy a typeable display-derived accessor it advertises; field IDs appear second for disambiguation.
|
|
50
|
+
|
|
49
51
|
### 3. Use only advertised syntax
|
|
50
52
|
|
|
51
53
|
Get the current operation catalog when needed:
|
|
@@ -56,11 +58,11 @@ cai expr ops --type <text|number|date|list|boolean|file|custom> --json
|
|
|
56
58
|
|
|
57
59
|
Keep the program to optional `const` declarations followed by one final expression. Do not use loops, assignments, `new`, regular expressions, optional chaining, arbitrary library methods, or object construction unless the current compiler catalog explicitly supports them.
|
|
58
60
|
|
|
59
|
-
Date values are ISO-8601 strings on the wire (`"2026-06-05"` or `"2026-06-05T12:30:00Z"`). A `date`-typed flow input or field is used directly with date operations; only `text` values need `.toDate()` first.
|
|
61
|
+
Date values are ISO-8601 strings on the wire (`"2026-06-05"` or `"2026-06-05T12:30:00Z"`). A `date`-typed flow input or field is used directly with date operations; only `text` values need `.toDate()` first. For epoch text, pass the unit literal explicitly: `flow.timestamp.toDate("epoch_seconds")` or `flow.timestamp.toDate("epoch_millis")`. The ops table renders that argument generically; never guess the unit from digit count.
|
|
60
62
|
|
|
61
63
|
Read [references/dsl-and-recipes.md](references/dsl-and-recipes.md) for canonical patterns.
|
|
62
64
|
|
|
63
|
-
### 4. Compile, write, and read back
|
|
65
|
+
### 4. Compile, write, and read back
|
|
64
66
|
|
|
65
67
|
For a node prop, prefer:
|
|
66
68
|
|
|
@@ -74,7 +76,9 @@ For multiline expressions or shell-sensitive templates, put the exact source in
|
|
|
74
76
|
cai expr set <nodeId> --prop <propName> --js-file expression.js --json
|
|
75
77
|
```
|
|
76
78
|
|
|
77
|
-
This fetches target metadata, compiles
|
|
79
|
+
This fetches target metadata, auto-enables a catalog-only optional target when needed, compiles before writing the value, persists to the correct channel, and verifies read-back. If validation or the value write then fails, the prop stays enabled; repair with `cai node disable-prop <nodeId> --prop <propName>`.
|
|
80
|
+
|
|
81
|
+
Array channels are not interchangeable. On a value-channel `SHORT_TEXT_ARRAY`, a scalar expression replaces the whole array with one dynamic element; it does not append. List-typed expressions on value-channel array props are rejected. Use `cai node set <nodeId> --prop <propName> --value '["a","b"]'` for a static list, or use a list-typed expression only where prop metadata exposes whole-array expression mode.
|
|
78
82
|
|
|
79
83
|
For a side-effect-free check:
|
|
80
84
|
|
|
@@ -103,6 +103,8 @@ Inside loop mappings, `item` exists only where context exposes it. Inside the bo
|
|
|
103
103
|
|
|
104
104
|
Loops run sequentially. `--continue-on-error` applies to a failed child iteration; a list expression or mapping/config expression that fails before the child starts still aborts the loop. Test empty, one-item, several-item, over-limit, and intended iteration-error behavior.
|
|
105
105
|
|
|
106
|
+
Never enable continue-on-error on a money path; charges, purchases, transfers, refunds, and other spend must fail fast.
|
|
107
|
+
|
|
106
108
|
## Subflows and convergence
|
|
107
109
|
|
|
108
110
|
Define the called flow's inputs and outputs first. Then initialize a Run flow component and bind it:
|
|
@@ -63,6 +63,8 @@ cai node status <nodeId> --json
|
|
|
63
63
|
cai node props <nodeId> --json
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
+
For option-backed props, `node props` and write readback may report `optionsAvailability`: `available`, `blocked_upstream` with `blockedBy`, or `dynamic_upstream`. It is positional: earlier single `DROPDOWN` selectors gate later options. Older backends, and responses without a dependency catalog, may omit it; treat absence as unknown, not available.
|
|
67
|
+
|
|
66
68
|
Work through blockers in this order:
|
|
67
69
|
|
|
68
70
|
1. Missing connection
|
|
@@ -73,7 +75,9 @@ Work through blockers in this order:
|
|
|
73
75
|
6. Expressions
|
|
74
76
|
7. Unresolved output type
|
|
75
77
|
|
|
76
|
-
|
|
78
|
+
Follow `next`. When a disabled required prop has an activating selector, its blocker names that selector; when it is the next blocker, `next` gives the exact `cai node set` command. `dynamicSelectorNotes` is non-blocking: a node may read ready while its dynamic selector's dependents still reflect the last concrete resolution.
|
|
79
|
+
|
|
80
|
+
After every concrete reload-selector or connection change, re-run `node props`; dynamic props can appear, disappear, or reset. Use `cai node reload <nodeId> --json` to re-resolve without re-setting a selector. If an explicit reload finds an unset materialized reload selector, it returns `reconcileSkipped: "unset_selector"` plus a note and preserves materialized dependent props instead of reconciling them.
|
|
77
81
|
|
|
78
82
|
### 5. Set props safely
|
|
79
83
|
|
|
@@ -87,10 +91,12 @@ Optional prop:
|
|
|
87
91
|
|
|
88
92
|
```bash
|
|
89
93
|
cai node optional-props <nodeId> --json
|
|
90
|
-
cai node
|
|
91
|
-
cai
|
|
94
|
+
cai node set <nodeId> --prop <exactName> --value '<literal-or-json>' --json
|
|
95
|
+
# or: cai expr set <nodeId> --prop <exactName> --js '<expression>' --json
|
|
92
96
|
```
|
|
93
97
|
|
|
98
|
+
`node set` and `expr set` auto-enable a catalog-only optional prop, refresh its metadata, then write. Do not run a separate enable step first. If validation or the later write fails, the prop stays enabled; repair with `cai node disable-prop <nodeId> --prop <exactName>` and re-read props. This is also the repair for the Update-data wipe footgun: that action writes every enabled field, so disable any accidentally enabled field before running it.
|
|
99
|
+
|
|
94
100
|
Remote or dynamic option:
|
|
95
101
|
|
|
96
102
|
```bash
|
|
@@ -102,7 +108,20 @@ cai node set <nodeId> \
|
|
|
102
108
|
--json
|
|
103
109
|
```
|
|
104
110
|
|
|
105
|
-
|
|
111
|
+
`node options` also supports `--prev-context '<context JSON>'` from the preceding page and repeatable `--for '<earlierProp>=<value>'` overrides for read-only hypothetical resolution; JSON literals are accepted and bare text stays a string. If options are `blocked_upstream`, both `node options` and `node set` name the blocking prop and print the exact `cai node set` command to run first.
|
|
112
|
+
|
|
113
|
+
For an ordinary remote option, preserve both fields from the same returned option. The label is not cosmetic: the CLI uses it to search providers that do not index opaque IDs, then verifies that the returned value still matches before writing. For a multi-select, pass a JSON array of returned values and one `--label` argument per value, in the same order. The CLI supplies the persisted label shape, chooses the correct expression storage channel, and verifies read-back.
|
|
114
|
+
|
|
115
|
+
When an earlier selector makes the prop `dynamic_upstream`, no option list exists. Use a known exact ID or an expression:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
cai node set <nodeId> --prop <exactName> --value '<exact-id>' --label '<display label>' --json
|
|
119
|
+
cai node set <nodeId> --prop <exactName> --js '<expression>' --json
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
`--value` stores the literal without provider-option validation and prints a note; on a label-bearing selector, `--label` controls its display label. This is the sole raw `--value` exception when the CLI has an advertised option set: outside `dynamic_upstream`, a missing prop row, a failed or empty advertised remote-options lookup, or a value absent from advertised options fails closed. The exception still requires prop metadata and verified read-back. Do not bypass failures with a raw API call.
|
|
123
|
+
|
|
124
|
+
For components whose dependent props exist only after a concrete selector value, use a template first: set one concrete value, re-read `node props`, configure or record the revealed dependents, then switch the selector to `--js`. Those materialized props persist as the last concrete schema. Starting dynamic leaves them absent; neither that write nor `node reload` materializes them until one concrete selection is made.
|
|
106
125
|
|
|
107
126
|
For dynamic values, load `controllerai-expressions` and prefer `cai expr set`.
|
|
108
127
|
|
|
@@ -125,14 +144,22 @@ cai run node <nodeId> --inputs <values.json> --json
|
|
|
125
144
|
|
|
126
145
|
If the node has a wired input or consumes `inputs.<name>`, the node test is only an isolated configuration check. Run `cai run flow <flowId> --inputs <values.json> --json` before declaring its upstream expressions verified.
|
|
127
146
|
|
|
147
|
+
If a dynamic provider action cannot be run but its response is documented, declare an unverified output contract:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
cai node declare-output <nodeId> --sample-file provider-response.json --json
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
The sample must be a JSON object or a non-empty JSON array of provider items. Re-read status and expression context afterward; the first real completed run verifies the declaration.
|
|
154
|
+
|
|
128
155
|
Read [references/prop-and-readiness.md](references/prop-and-readiness.md) when a prop is dynamic, option-backed, expression-capable, or unexpectedly absent.
|
|
129
156
|
|
|
130
157
|
## Hard rules
|
|
131
158
|
|
|
132
159
|
- Configure props in returned order; later props may depend on earlier values.
|
|
133
160
|
- Never write a prop absent from `node props`.
|
|
134
|
-
-
|
|
161
|
+
- Let `node set` or `expr set` auto-enable catalog-only optional props; disable the prop explicitly after a failed write.
|
|
135
162
|
- Wire before authoring an expression that consumes upstream data.
|
|
136
163
|
- Changing a connection invalidates connection-scoped options; re-read props and options.
|
|
137
164
|
- A successful write is not completion. Require read-back plus `node status`.
|
|
138
|
-
- If output type remains unresolved, perform a realistic development test and inspect the resulting execution.
|
|
165
|
+
- If output type remains unresolved, perform a realistic development test and inspect the resulting execution. Declare only a documented provider sample; never fabricate an output schema.
|
|
@@ -6,7 +6,9 @@ The JSON response reports:
|
|
|
6
6
|
|
|
7
7
|
- `missingConnection`: an authenticated component has no account bound.
|
|
8
8
|
- `missingRequiredProps`: materialized required props without a value.
|
|
9
|
+
- `disabledRequiredProps`: required props currently disabled by an activating selector. When that selector can be resolved, its blocker names the selector; when it is next, `next` gives the exact `cai node set` command.
|
|
9
10
|
- `pendingReloadProps`: selectors that must be set before dependent props are trustworthy.
|
|
11
|
+
- `dynamicSelectorNotes`: reload selectors holding dynamic values whose dependents were not re-resolved. These notes do not block readiness, so inspect them even when the node reads ready.
|
|
10
12
|
- `outputTypeStatus`: `concrete`, `unresolved`, or `none`. Connection-port wrappers never count as a concrete process output.
|
|
11
13
|
- `readyForExpressions`: connection and required/reload props are complete. The source still must be wired before its binding appears in expression context.
|
|
12
14
|
- `readyForRun`: connection and required/reload props are complete; running may be the step that discovers a concrete output type.
|
|
@@ -40,6 +42,14 @@ Do not force a channel with internal fields. `cai node set` and `cai expr set` c
|
|
|
40
42
|
|
|
41
43
|
Static options are declared in component/prop metadata. Remote options require current connection and earlier prop values.
|
|
42
44
|
|
|
45
|
+
When dependency metadata is available, each option-bearing prop reports:
|
|
46
|
+
|
|
47
|
+
- `available`: no earlier selector blocks option resolution; connection or provider failures can still stop the lookup.
|
|
48
|
+
- `blocked_upstream` with `blockedBy`: an earlier single `DROPDOWN` selector is unset.
|
|
49
|
+
- `dynamic_upstream`: an earlier single `DROPDOWN` selector is dynamic, so no concrete option list exists.
|
|
50
|
+
|
|
51
|
+
The backend computes this in prop order. Older backends, and current responses without a dependency catalog, omit these fields; do not interpret absence as `available`.
|
|
52
|
+
|
|
43
53
|
```bash
|
|
44
54
|
cai node options <nodeId> --prop <name> --query "<specific search>" --json
|
|
45
55
|
cai node set <nodeId> --prop <name> --value '<option.value>' --label '<option.label>' --json
|
|
@@ -47,6 +57,20 @@ cai node set <nodeId> --prop <name> --value '<option.value>' --label '<option.la
|
|
|
47
57
|
|
|
48
58
|
Pass the value and label from the same live option. Remote providers often search labels rather than opaque values, so omitting `--label` can make a valid copied ID impossible to re-verify. For multi-select, pass a JSON array of returned values plus one `--label` argument per value in matching order. The CLI constructs the required array of `{value,label}` records for read-back/UI compatibility.
|
|
49
59
|
|
|
60
|
+
Continue a provider page with the opaque context printed by the previous call:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
cai node options <nodeId> --prop <name> --prev-context '<context JSON>' --json
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Preview options under uncommitted earlier values with repeatable overrides; valid JSON becomes a typed literal and bare text remains a string:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
cai node options <nodeId> --prop <name> --for '<selector>=<value>' --for '<other>=true' --json
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
For `blocked_upstream`, follow the error's exact command for `blockedBy`. For `dynamic_upstream`, `node options` returns no list; `node set --value '<exact-id>'` deliberately stores a known literal without provider membership validation and prints a note. Add `--label '<display label>'` when the prop is label-bearing, or use `node set --js '<expression>'`. For an advertised option set outside that state, a missing prop row, a failed or empty advertised remote-options lookup, or a value absent from advertised options fails closed.
|
|
73
|
+
|
|
50
74
|
## Reload selectors
|
|
51
75
|
|
|
52
76
|
A prop with `reloadProps:true` changes the downstream prop schema. Set it statically, wait for the mutation, and immediately re-read:
|
|
@@ -57,8 +81,18 @@ cai node props <nodeId> --json
|
|
|
57
81
|
cai node status <nodeId> --json
|
|
58
82
|
```
|
|
59
83
|
|
|
84
|
+
Use `cai node reload <nodeId> --json` to re-resolve current values explicitly instead of re-setting a selector. If any materialized reload selector is unset, the command returns `reconcileSkipped: "unset_selector"` and a note; that skipped path updates metadata without reconciling or deleting materialized dependent props.
|
|
85
|
+
|
|
60
86
|
Do not batch dependent values into stale metadata. A provider, model family, spreadsheet, database, or action selector commonly triggers this behavior.
|
|
61
87
|
|
|
88
|
+
For a component whose dependent schema exists only after a concrete upstream selection, materialize a template before going dynamic:
|
|
89
|
+
|
|
90
|
+
1. Set the selector to one concrete value.
|
|
91
|
+
2. Re-read props and configure or record the revealed dependents.
|
|
92
|
+
3. Switch the selector to a dynamic value with `--js`.
|
|
93
|
+
|
|
94
|
+
The dependent props persist from the last concrete selection. Starting with a dynamic selector leaves them absent, and neither the dynamic write nor an explicit reload can materialize them until the selector has held a concrete value once.
|
|
95
|
+
|
|
62
96
|
## Output type
|
|
63
97
|
|
|
64
98
|
An unresolved output blocks trustworthy downstream field expressions. Resolve it by one of:
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: controllerai-runs
|
|
3
|
-
description: Run and debug Controller AI nodes and flows on the
|
|
3
|
+
description: Run and debug Controller AI nodes on development and flows on development or the published live version — execution history, ports, outputs, skip reasons, and resolved configs. Use when verifying or testing a build, investigating a failed or green-but-wrong run, resolving an unknown output type, checking expression values, or proving what data and configuration reached each node.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Controller AI runs
|
|
7
7
|
|
|
8
|
-
Think "
|
|
8
|
+
Think "real run", not "simulation". `run node` always uses development; `run flow` defaults to development and can target the published live version. Both rails execute real integration actions (messages send, records change, provider usage is spent); development isolation covers the data store only. Running is a required part of building — one successful run is how a dynamic node's output type gets resolved for the next step — so mitigate risk before running.
|
|
9
9
|
|
|
10
10
|
## Consequential actions: mitigate with the user, don't refuse
|
|
11
11
|
|
|
12
|
-
Before
|
|
12
|
+
Before running an action with external consequences (send, reject, delete, charge), tell the user plainly what will really happen and ask for a safe target:
|
|
13
13
|
|
|
14
14
|
- Email/message sends → "What address/channel can I send the dev run to?" (often the user's own).
|
|
15
15
|
- Record deletes/updates → "Is there a record I can safely use, or shall I create one first and delete that?"
|
|
@@ -25,7 +25,13 @@ cai node declare-output <nodeId> --sample-file shape.json
|
|
|
25
25
|
|
|
26
26
|
## First live run is part of development
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
After publishing, run the published version directly under supervision:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
cai run flow <flowId> --inputs values.json --target live --confirm-live --json
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
This command fires external actions and spends usage. For risky sends, build the safe-audience harness: branch on the `isLiveVersion` data source with If/Else — the false branch targets the developer (own email/channel), the true branch targets the real audience. Use this direct live run for explicit verification; do not wait for a real trigger event.
|
|
29
35
|
|
|
30
36
|
## Prepare exact run inputs
|
|
31
37
|
|
|
@@ -44,6 +50,8 @@ Use returned opaque input IDs. A compact input file can be a flat map:
|
|
|
44
50
|
|
|
45
51
|
Do not key test values by a guessed display name.
|
|
46
52
|
|
|
53
|
+
Before an isolated node run, `cai run inputs <nodeId> --json` calls `get_node_test_inputs`; supply every referenced `flowInputs[].id` explicitly. Missing one fails before execution with `ISOLATED_FLOW_CONTEXT_REQUIRED`. Explicit `null`, `""`, `false`, and `0` are valid supplied values.
|
|
54
|
+
|
|
47
55
|
Date-typed inputs take plain ISO-8601 strings, e.g. `"2026-06-05"` or `"2026-06-05T12:30:00Z"` (no double-encoding, no epoch strings).
|
|
48
56
|
|
|
49
57
|
## Run the smallest useful scope
|
|
@@ -65,6 +73,7 @@ For every node test, inspect:
|
|
|
65
73
|
- `skipReason`
|
|
66
74
|
- `runScope`, especially `upstreamNodesExecuted` and `endToEndValidationRequired`
|
|
67
75
|
- `resolvedConfigs`
|
|
76
|
+
- `resolvedConfigs[].resolutionWarnings`: trust every structured entry; `[]` is authoritatively clean. Runs also surface entries on stderr, so read stderr even when the execution completed.
|
|
68
77
|
- `outputTypeAdoption`: the server verifies the exact completed `nodeExecutionId`, derives its persisted output shape, and updates only that non-static node. `adopted` or `already_typed` lets the next `node status` converge; `no_observed_output` means the representative run returned no reusable shape. `adoptedNodeIds` must be empty or contain only the tested node; stop if it names a sibling.
|
|
69
78
|
- output shape and values
|
|
70
79
|
|
|
@@ -101,6 +110,7 @@ After successful output discovery, re-read `cai node status` and downstream `cai
|
|
|
101
110
|
|
|
102
111
|
## Completion gate
|
|
103
112
|
|
|
113
|
+
- Gate scripts on `cai workflow validate`; it exits 1 when the response has `valid: false`.
|
|
104
114
|
- The test exercised the changed path with credible values.
|
|
105
115
|
- The first unexpected node, if any, was identified rather than inferred from the final error.
|
|
106
116
|
- All dynamic configs resolved to intended values.
|
|
@@ -9,7 +9,7 @@ cai workflow status --json
|
|
|
9
9
|
cai flow get <flowId> --json
|
|
10
10
|
```
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
Node runs use development. Flow runs default to development; `cai run flow <flowId> --target live --confirm-live` runs the published version. Trigger replay also defaults to development and uses the same flags for live. Every rail can call real providers and create external effects.
|
|
13
13
|
|
|
14
14
|
## 2. Find the first divergence
|
|
15
15
|
|
|
@@ -44,5 +44,6 @@ The platform reference lives at https://docs.getcontroller.ai. Fetch https://doc
|
|
|
44
44
|
- Local coding-agent subscriptions cover builder reasoning, not Controller AI hosted-agent runtime usage.
|
|
45
45
|
- Provider actions can send messages, mutate or delete records, and incur provider charges. Decide the per-action confirmation policy before attaching one.
|
|
46
46
|
- Never publish, share with the organization, replay a live trigger, or perform a consequential external test without clear user intent.
|
|
47
|
+
- When a platform limitation blocks the outcome, STOP and report the partial result with the blocking error; never keep probing until the clock expires.
|
|
47
48
|
|
|
48
49
|
At completion, report what was created, what is still draft or live, the evidence actually observed, and any connection or user decision still required.
|
|
@@ -16,12 +16,16 @@ cai use <workflowId>
|
|
|
16
16
|
cai workflow status --json
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
If no workflow exists, create
|
|
19
|
+
If no workflow exists, create it with its final name:
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
22
|
cai workflow create --name "<clear outcome-oriented name>" --json
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
+
Read `selected`, `effectiveWorkflowId`, and `pinSource` from the result; creation does not guarantee that the new workflow won the effective pin. If `selected` is false, rerun without `--workflow` when `pinSource` is `flag`; otherwise run `cai use <id>` for a stored pin or clear an inherited `CAI_WORKFLOW` pin in the parent environment, then re-check context. Use `cai config reset` to clear stale stored pins; it cannot clear an environment pin. `cai doctor` verifies that the effective workflow pin and its development head are readable. Do not create and then rename: `workflow create --name` submits the name directly.
|
|
26
|
+
|
|
27
|
+
A new workflow already ships with one empty flow. Rename that flow and build in it — do not add a second flow for the first piece of work; only add flows for genuinely separate canvases. A stray empty "Flow 1" left behind is clutter the user has to clean up.
|
|
28
|
+
|
|
25
29
|
Use IDs returned by the CLI. Never invent workflow, flow, node, prop, event, field, route, or connection identifiers.
|
|
26
30
|
|
|
27
31
|
To orient inside a workflow, prefer one call over many:
|
|
@@ -38,8 +42,9 @@ It returns the whole map compactly — every flow with typed inputs/outputs, its
|
|
|
38
42
|
2. Inspect the current workflow before editing: `cai workflow outline`, then `cai flow get <flowId>` for the flows you will touch.
|
|
39
43
|
3. Create or select a flow. Define flow inputs and outputs before nodes that derive props from them.
|
|
40
44
|
4. Build in execution order. After each material change, read it back with the corresponding `get`, `props`, `status`, or `list` command.
|
|
41
|
-
5.
|
|
42
|
-
6.
|
|
45
|
+
5. After a headless build, run `cai flow layout <flowId>` once per changed flow at the end; an open builder auto-tidies itself.
|
|
46
|
+
6. Test on the development rail. Debug every failed or suspicious node; a green top-level status alone is insufficient.
|
|
47
|
+
7. Re-read `cai workflow status`. Publish only when the user asked for a live change or clearly authorized deployment.
|
|
43
48
|
|
|
44
49
|
For multi-domain work, read [references/command-map.md](references/command-map.md) before editing.
|
|
45
50
|
|
|
@@ -59,18 +64,18 @@ Load the narrow skill when the task reaches that surface:
|
|
|
59
64
|
## Lifecycle rules
|
|
60
65
|
|
|
61
66
|
- All graph edits target development. Live remains unchanged until `cai workflow publish`.
|
|
62
|
-
- Prefer `--json` for decisions and IDs; human tables are for presentation.
|
|
67
|
+
- Prefer `--json` for decisions and IDs; human tables are for presentation. If human output looks odd, re-run the same read with `--json` before acting.
|
|
63
68
|
- A workflow contains flows; a flow is one canvas. Do not confuse their IDs.
|
|
64
|
-
- For flow inputs, pass a human `--display` label and
|
|
69
|
+
- For flow inputs, pass a human `--display` label and use the compiler-current binding from the latest `cai flow get` (`jsBinding`) or `cai workflow outline` (`binding`). An input rename can change it: re-read bindings after every rename and never cache their spellings across renames. `legacyBinding` is diagnostic-only; never use it in expressions.
|
|
65
70
|
- Name nodes after the data they produce. Downstream input bindings are seeded from that name when wired.
|
|
66
|
-
- Use `cai workflow save --name "<checkpoint>"` before a risky rewrite
|
|
67
|
-
- **Edit the graph with
|
|
71
|
+
- Use `cai workflow save --name "<checkpoint>"` before a risky rewrite. Named saves and state renames work on every plan.
|
|
72
|
+
- **Edit the graph with a plan-aware safety net.** Each save is a version state. `cai workflow history` has no age cutoff on Free, Max, or custom plans and a 90-day window on Pro/Starter; expand a group with `cai workflow history --group <groupId>` to get its state IDs. Restore with `cai workflow restore --state <stateId>` within 7 days on Free, 90 days on Pro/Starter, or without an age limit on Max/custom. Duplicate, delete, and refactor with that window in mind. Restore rolls back the DEFINITION (graph and schemas) only — record data is unversioned and stays as it is. External side effects (sent messages, provider calls) are equally outside the undo.
|
|
68
73
|
- **Validate after structural edits, don't ask permission before them.** After deleting a flow, deleting a type, or a large refactor — and before publish — run `cai workflow validate` and fix what it lists: unlinked subflow callers, dangling type references, branch problems, trigger issues. Deleting a flow deletes its nodes, edges, inputs/outputs, and attached triggers, and breaks callers in other flows — exactly like deleting a function breaks its call sites; validate shows every break.
|
|
69
74
|
- On a conflict, re-read current state and reapply intent. Do not replay stale IDs or whole documents.
|
|
70
75
|
- Never delete a workflow without the user's explicit intent; the CLI requires `--yes` but that is not a substitute for authorization. `cai workflow delete` tears down deployed triggers and soft-deletes the workflow row. Historical workflow/version data remains stored, but there is currently no CLI restore command for the deleted row.
|
|
71
76
|
- **Know the dependency graph before deleting or refactoring shared resources.** `cai deps` shows which agents attach this workflow as a tool (LIVE or draft), which workflows call it, and which connections it uses; `cai deps --account` maps the whole account. Deleting a workflow that agents depend on is refused with the dependents named — bring that list to the user, then `--force` only on their informed choice (a LIVE agent changes behavior immediately).
|
|
72
77
|
- **Check the account feed when recent activity matters.** `cai events` lists what happened in the account, newest first: connections created, workflow edits/publishes/runs, agents created/published, members added. Filter with `--type` (comma-separated), `--since 30m|2h|7d|<ISO>`, `--for-workflow <id>`; page with `--cursor`. Typical uses: `cai events --type connection.created --since 10m` to see whether the user finished connecting, `cai events --since 24h` to catch up at session start, `cai events --for-workflow <id> --type workflow.run` for recent run activity. The feed cannot show connection deletions, settings changes, or member removals — absence there proves nothing.
|
|
73
|
-
- **Share the platform, not just text.** At the right moments, hand the user the real product page — command outputs include `appUrl` when the app origin is known: after `workflow publish` (the live builder view), after `run flow`/`run node` (the run page
|
|
78
|
+
- **Share the platform, not just text.** At the right moments, hand the user the real product page — command outputs include `appUrl` when the app origin is known: after `workflow publish` (the live builder view), after development `run flow`/`run node` (the run page; live flow runs omit it), after `agent publish`/`test` (agent and conversation pages), and `connection connect` prints the connect link (use `--wait` to continue automatically once they connect). When the user asks for a link at any other time, don't guess URLs: `cai workflow get`, `cai workflow status`, and `cai agent get` include `appUrl`. When you cannot perform something (settings, product-only surfaces), give the link instead of apologizing.
|
|
74
79
|
- Never silently weaken the request to make a test pass. Report an unsupported capability or ask about a real product decision.
|
|
75
80
|
|
|
76
81
|
## Completion gate
|
|
@@ -7,6 +7,7 @@ Read only the sections relevant to the requested work. Use `cai <domain> --help`
|
|
|
7
7
|
```text
|
|
8
8
|
cai connect
|
|
9
9
|
cai doctor
|
|
10
|
+
cai config reset [--local|--global]
|
|
10
11
|
cai auth status
|
|
11
12
|
cai workflow list|create|get|rename|describe|duplicate|delete
|
|
12
13
|
cai workflow state|status|versions|releases|history|save|restore|publish
|
|
@@ -18,7 +19,7 @@ cai use <workflowId>
|
|
|
18
19
|
## Canvas and graph
|
|
19
20
|
|
|
20
21
|
```text
|
|
21
|
-
cai flow list|get|create|rename|duplicate|delete|reorder
|
|
22
|
+
cai flow list|get|create|rename|duplicate|delete|reorder|layout
|
|
22
23
|
cai flow input add|update|delete
|
|
23
24
|
cai flow output add|update|delete
|
|
24
25
|
cai node find|search|components|component
|
|
@@ -27,7 +28,7 @@ cai node init|status|get|props|set|connect|disconnect|delete
|
|
|
27
28
|
|
|
28
29
|
Declare flow outputs before adding a Return response node. Its props are derived from those outputs.
|
|
29
30
|
|
|
30
|
-
`cai flow input add <flowId> --display "<human label>" --type <type>` returns the
|
|
31
|
+
`cai flow input add <flowId> --display "<human label>" --type <type>` returns the compiler-current `jsBinding`. Use the latest value from `flow get` (`jsBinding`) or `workflow outline` (`binding`), re-read it after every input rename, and never cache its spelling across renames. `legacyBinding` is diagnostic-only.
|
|
31
32
|
|
|
32
33
|
## Conditions and composition
|
|
33
34
|
|