@culvii/cli 0.0.8 → 0.1.0

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.
Files changed (65) hide show
  1. package/dist/{HelpView-E7HS4SVF.js → HelpView-NKJCCU5A.js} +1 -1
  2. package/dist/{chunk-IPETC2TK.js → chunk-D3YFBXU5.js} +1 -1
  3. package/dist/index.js +25 -27
  4. package/dist/lib/evaluator.js +2 -2
  5. package/dist/{login-OGOHEHFE.js → login-7VBXFHFC.js} +1 -1
  6. package/dist/{logout-BRUJBFUK.js → logout-OJRK2KGE.js} +1 -1
  7. package/dist/skill-bundle-5WQTV2OV.js +2553 -0
  8. package/package.json +2 -2
  9. package/skills/culvii/.culvii-skill.json +58 -27
  10. package/skills/culvii/SKILL.md +31 -0
  11. package/skills/culvii/examples/agent-workflow.culvii.ts +28 -5
  12. package/skills/culvii/examples/binary-document-workflow.culvii.ts +80 -0
  13. package/skills/culvii/examples/complete-workflow.culvii.ts +55 -11
  14. package/skills/culvii/examples/custom-output-surface.culvii.ts +69 -0
  15. package/skills/culvii/examples/custom-wait-surface.culvii.ts +90 -0
  16. package/skills/culvii/examples/human-in-the-loop-workflow.culvii.ts +125 -0
  17. package/skills/culvii/examples/integration-agent-workflow.culvii.ts +101 -0
  18. package/skills/culvii/examples/multi-agent-workflow-tools.culvii.ts +157 -0
  19. package/skills/culvii/examples/nested-agent-workflow.culvii.ts +108 -0
  20. package/skills/culvii/references/agents.md +53 -5
  21. package/skills/culvii/references/cli-guide.md +1 -1
  22. package/skills/culvii/references/cli-reference.md +33 -0
  23. package/skills/culvii/references/feedback-cycle.md +1 -1
  24. package/skills/culvii/references/kit-api.md +2 -2
  25. package/skills/culvii/references/node-argocd.md +44 -0
  26. package/skills/culvii/references/node-clickup-doc.md +38 -0
  27. package/skills/culvii/references/node-clickup-ticket.md +47 -0
  28. package/skills/culvii/references/node-core-loop-break.md +26 -0
  29. package/skills/culvii/references/node-core-loop-continue.md +26 -0
  30. package/skills/culvii/references/node-core-loop-output.md +24 -0
  31. package/skills/culvii/references/node-core-loop.md +25 -0
  32. package/skills/culvii/references/node-core-merge.md +23 -0
  33. package/skills/culvii/references/node-core-switch.md +24 -0
  34. package/skills/culvii/references/node-cost-explorer.md +45 -0
  35. package/skills/culvii/references/node-elasticsearch.md +2 -2
  36. package/skills/culvii/references/node-github-poll-trigger.md +31 -0
  37. package/skills/culvii/references/node-github-webhook-trigger.md +27 -0
  38. package/skills/culvii/references/node-github.md +251 -0
  39. package/skills/culvii/references/node-gmail-trigger.md +2 -2
  40. package/skills/culvii/references/node-gmail.md +2 -2
  41. package/skills/culvii/references/node-google-calendar.md +2 -2
  42. package/skills/culvii/references/node-google-docs.md +2 -2
  43. package/skills/culvii/references/node-grafana-dashboard.md +38 -0
  44. package/skills/culvii/references/node-grafana-data-source.md +42 -0
  45. package/skills/culvii/references/node-grafana-query.md +34 -0
  46. package/skills/culvii/references/node-hibp-list-domains.md +27 -0
  47. package/skills/culvii/references/node-hibp-stealer-logs.md +30 -0
  48. package/skills/culvii/references/node-kubernetes.md +51 -0
  49. package/skills/culvii/references/node-microsoft-outlook-trigger.md +2 -2
  50. package/skills/culvii/references/node-microsoft-outlook.md +3 -2
  51. package/skills/culvii/references/node-microsoft-sharepoint.md +2 -2
  52. package/skills/culvii/references/node-onionsearch.md +27 -0
  53. package/skills/culvii/references/node-prometheus.md +40 -0
  54. package/skills/culvii/references/node-s3.md +2 -2
  55. package/skills/culvii/references/node-slack-events-trigger.md +37 -0
  56. package/skills/culvii/references/node-slack-interactions-trigger.md +28 -0
  57. package/skills/culvii/references/node-slack-trigger.md +2 -2
  58. package/skills/culvii/references/node-slack.md +128 -4
  59. package/skills/culvii/references/node-supabase.md +61 -0
  60. package/skills/culvii/references/node-twilio.md +2 -2
  61. package/skills/culvii/references/nodes-index.md +24 -0
  62. package/skills/culvii/references/surface-authoring.md +12 -1
  63. package/skills/culvii/references/surface-display.md +1 -1
  64. package/skills/culvii/references/surface-feedback.md +24 -27
  65. package/dist/skill-bundle-7KYK5GBL.js +0 -1377
@@ -2,7 +2,7 @@
2
2
 
3
3
  - Type ID: `slack`
4
4
  - Kind: `action`
5
- - Credentials: required as `credentials: { name, id }`
5
+ - Credentials: required as `credentials: { name, id }`; `name` must be one of: `slack_bot`, `slack_user`
6
6
  - Feedback mock: required
7
7
 
8
8
  Resolve the credential through [integration selection](integrations.md); never ask the user to copy a credential ID.
@@ -10,17 +10,141 @@ Resolve the credential through [integration selection](integrations.md); never a
10
10
  ## Props
11
11
 
12
12
  - `resource`: options; required
13
- - Values: `message`
13
+ - Values: `message`, `reaction`, `user`, `channel`, `file`, `search`, `interaction`
14
14
  - `operation`: options; required; when resource=message
15
- - Values: `send`
15
+ - Values: `send`, `sendByEmail`, `update`, `delete`, `getReplies`, `getPermalink`, `schedule`, `listScheduled`, `cancelScheduled`, `sendEphemeral`
16
16
  - `channel`: string; required; when resource=message, operation=send
17
17
  - `text`: string; required; when resource=message, operation=send
18
18
  - `additionalFields`: object; optional; when resource=message, operation=send
19
19
  - `thread_ts`: string; optional
20
+ - `reply_broadcast`: boolean; optional
21
+ - `blocks`: json; optional
20
22
  - `mrkdwn`: boolean; optional
21
23
  - `link_names`: boolean; optional
22
24
  - `unfurl_links`: boolean; optional
23
25
  - `unfurl_media`: boolean; optional
26
+ - `email`: string; required; when resource=message, operation=sendByEmail
27
+ - `text`: string; required; when resource=message, operation=sendByEmail
28
+ - `messageOptions`: object; optional; when resource=message, operation=sendByEmail
29
+ - `blocks`: json; optional
30
+ - `mrkdwn`: boolean; optional
31
+ - `link_names`: boolean; optional
32
+ - `unfurl_links`: boolean; optional
33
+ - `unfurl_media`: boolean; optional
34
+ - `channel`: string; required; when resource=message, operation=sendEphemeral
35
+ - `userId`: string; required; when resource=message, operation=sendEphemeral
36
+ - `text`: string; required; when resource=message, operation=sendEphemeral
37
+ - `ephemeralOptions`: object; optional; when resource=message, operation=sendEphemeral
38
+ - `thread_ts`: string; optional
39
+ - `blocks`: json; optional
40
+ - `link_names`: boolean; optional
41
+ - `channel`: string; required; when resource=message, operation=schedule
42
+ - `text`: string; required; when resource=message, operation=schedule
43
+ - `postAt`: dateTime; required; when resource=message, operation=schedule
44
+ - `scheduleOptions`: object; optional; when resource=message, operation=schedule
45
+ - `thread_ts`: string; optional
46
+ - `reply_broadcast`: boolean; optional
47
+ - `blocks`: json; optional
48
+ - `link_names`: boolean; optional
49
+ - `unfurl_links`: boolean; optional
50
+ - `unfurl_media`: boolean; optional
51
+ - `channelId`: string; optional; when resource=message, operation=listScheduled
52
+ - `oldest`: dateTime; optional; when resource=message, operation=listScheduled
53
+ - `latest`: dateTime; optional; when resource=message, operation=listScheduled
54
+ - `limit`: number; optional; when resource=message, operation=listScheduled
55
+ - `cursor`: string; optional; when resource=message, operation=listScheduled
56
+ - `channelId`: string; required; when resource=message, operation=cancelScheduled
57
+ - `scheduledMessageId`: string; required; when resource=message, operation=cancelScheduled
58
+ - `channelId`: string; required; when resource=message, operation=update
59
+ - `messageTs`: string; required; when resource=message, operation=update
60
+ - `text`: string; required; when resource=message, operation=update
61
+ - `blocks`: json; optional; when resource=message, operation=update
62
+ - `channelId`: string; required; when resource=message, operation=delete
63
+ - `messageTs`: string; required; when resource=message, operation=delete
64
+ - `channelId`: string; required; when resource=message, operation=getReplies
65
+ - `threadTs`: string; required; when resource=message, operation=getReplies
66
+ - `limit`: number; optional; when resource=message, operation=getReplies
67
+ - `output`: options; optional; when resource=message, operation=getReplies
68
+ - Values: `simple`, `raw`
69
+ - `cursor`: string; optional; when resource=message, operation=getReplies
70
+ - `channelId`: string; required; when resource=message, operation=getPermalink
71
+ - `messageTs`: string; required; when resource=message, operation=getPermalink
72
+ - `operation`: options; required; when resource=reaction
73
+ - Values: `add`, `remove`
74
+ - `channelId`: string; required; when resource=reaction, operation=add
75
+ - `messageTs`: string; required; when resource=reaction, operation=add
76
+ - `emoji`: string; required; when resource=reaction, operation=add
77
+ - `channelId`: string; required; when resource=reaction, operation=remove
78
+ - `messageTs`: string; required; when resource=reaction, operation=remove
79
+ - `emoji`: string; required; when resource=reaction, operation=remove
80
+ - `operation`: options; required; when resource=user
81
+ - Values: `getByEmail`, `getMany`, `getProfile`, `updateProfile`
82
+ - `email`: string; required; when resource=user, operation=getByEmail
83
+ - `output`: options; optional; when resource=user, operation=getByEmail
84
+ - Values: `simple`, `raw`
85
+ - `limit`: number; optional; when resource=user, operation=getMany
86
+ - `output`: options; optional; when resource=user, operation=getMany
87
+ - Values: `simple`, `raw`
88
+ - `cursor`: string; optional; when resource=user, operation=getMany
89
+ - `user`: string; optional; when resource=user, operation=getProfile
90
+ - `user`: string; optional; when resource=user, operation=updateProfile
91
+ - `clearStatus`: boolean; optional; when resource=user, operation=updateProfile
92
+ - `status_text`: string; optional; when resource=user, operation=updateProfile
93
+ - `status_emoji`: string; optional; when resource=user, operation=updateProfile
94
+ - `status_expiration`: string; optional; when resource=user, operation=updateProfile
95
+ - `first_name`: string; optional; when resource=user, operation=updateProfile
96
+ - `last_name`: string; optional; when resource=user, operation=updateProfile
97
+ - `email`: string; optional; when resource=user, operation=updateProfile
98
+ - `operation`: options; required; when resource=channel
99
+ - Values: `getMany`, `create`, `archive`, `setTopic`, `invite`, `remove`
100
+ - `channelTypes`: options; optional; when resource=channel, operation=getMany
101
+ - Values: `public`, `private`, `publicAndPrivate`, `directMessages`, `groupDirectMessages`, `all`
102
+ - `excludeArchived`: boolean; optional; when resource=channel, operation=getMany
103
+ - `limit`: number; optional; when resource=channel, operation=getMany
104
+ - `output`: options; optional; when resource=channel, operation=getMany
105
+ - Values: `simple`, `raw`
106
+ - `cursor`: string; optional; when resource=channel, operation=getMany
107
+ - `channelName`: string; required; when resource=channel, operation=create
108
+ - `isPrivate`: boolean; optional; when resource=channel, operation=create
109
+ - `channelId`: string; required; when resource=channel, operation=archive
110
+ - `channelId`: string; required; when resource=channel, operation=setTopic
111
+ - `topic`: string; required; when resource=channel, operation=setTopic
112
+ - `channelId`: string; required; when resource=channel, operation=invite
113
+ - `userIds`: string; required; when resource=channel, operation=invite
114
+ - `channelId`: string; required; when resource=channel, operation=remove
115
+ - `userId`: string; required; when resource=channel, operation=remove
116
+ - `operation`: options; required; when resource=file
117
+ - Values: `upload`, `getInfo`, `download`
118
+ - `binaryPropertyName`: string; required; when resource=file, operation=upload
119
+ - `channelId`: string; optional; when resource=file, operation=upload
120
+ - `uploadOptions`: object; optional; when resource=file, operation=upload
121
+ - `filename`: string; optional
122
+ - `title`: string; optional
123
+ - `initial_comment`: string; optional
124
+ - `thread_ts`: string; optional
125
+ - `alt_txt`: string; optional
126
+ - `fileId`: string; required; when resource=file, operation=getInfo
127
+ - `output`: options; optional; when resource=file, operation=getInfo
128
+ - Values: `simple`, `raw`
129
+ - `fileId`: string; required; when resource=file, operation=download
130
+ - `binaryPropertyName`: string; required; when resource=file, operation=download
131
+ - `operation`: options; required; when resource=search
132
+ - Values: `messages`, `files`
133
+ - `query`: string; required; when resource=search
134
+ - `count`: number; optional; when resource=search
135
+ - `page`: number; optional; when resource=search
136
+ - `sort`: options; optional; when resource=search
137
+ - Values: `score`, `timestamp`
138
+ - `sort_dir`: options; optional; when resource=search
139
+ - Values: `asc`, `desc`
140
+ - `operation`: options; required; when resource=interaction
141
+ - Values: `respond`
142
+ - `responseUrl`: string; required; when resource=interaction, operation=respond
143
+ - `text`: string; optional; when resource=interaction, operation=respond
144
+ - `blocks`: json; optional; when resource=interaction, operation=respond
145
+ - `replaceOriginal`: boolean; optional; when resource=interaction, operation=respond
146
+ - `responseType`: options; optional; when resource=interaction, operation=respond
147
+ - Values: `in_channel`, `ephemeral`
24
148
  - `pauseAfterExecution`: boolean; optional
25
149
 
26
150
  ## Example
@@ -30,7 +154,7 @@ new Step({
30
154
  id: 'slack',
31
155
  name: 'slack',
32
156
  type: 'slack',
33
- credentials: { name: 'Stored credential', id: 'credential-id' },
157
+ credentials: { name: 'slack_bot', id: 'credential-id' },
34
158
  params: { /* use the required props and conditional values above */ },
35
159
  });
36
160
  ```
@@ -0,0 +1,61 @@
1
+ # supabase
2
+
3
+ - Type ID: `supabase`
4
+ - Kind: `action`
5
+ - Credentials: required as `credentials: { name, id }`; `name` must be one of: `supabase`
6
+ - Feedback mock: required
7
+
8
+ Resolve the credential through [integration selection](integrations.md); never ask the user to copy a credential ID.
9
+
10
+ ## Props
11
+
12
+ - `resource`: options; required
13
+ - Values: `database`, `storage`
14
+ - `operation`: options; required; when resource=database
15
+ - Values: `getRows`, `insertRow`, `updateRows`, `upsertRow`, `deleteRows`, `callFunction`
16
+ - `operation`: options; required; when resource=storage
17
+ - Values: `uploadFile`, `downloadFile`, `listFiles`, `deleteFile`
18
+ - `table`: string; required; when resource=database, operation=getRows
19
+ - `columns`: string; optional; when resource=database, operation=getRows
20
+ - `filters`: json; optional; when resource=database, operation=getRows
21
+ - `order`: string; optional; when resource=database, operation=getRows
22
+ - `limit`: number; optional; when resource=database, operation=getRows
23
+ - `table`: string; required; when resource=database, operation=insertRow
24
+ - `rowData`: json; required; when resource=database, operation=insertRow
25
+ - `table`: string; required; when resource=database, operation=updateRows
26
+ - `filters`: json; required; when resource=database, operation=updateRows
27
+ - `rowData`: json; required; when resource=database, operation=updateRows
28
+ - `table`: string; required; when resource=database, operation=upsertRow
29
+ - `rowData`: json; required; when resource=database, operation=upsertRow
30
+ - `onConflict`: string; optional; when resource=database, operation=upsertRow
31
+ - `table`: string; required; when resource=database, operation=deleteRows
32
+ - `filters`: json; required; when resource=database, operation=deleteRows
33
+ - `functionName`: string; required; when resource=database, operation=callFunction
34
+ - `args`: json; optional; when resource=database, operation=callFunction
35
+ - `bucket`: string; required; when resource=storage, operation=uploadFile
36
+ - `filePath`: string; required; when resource=storage, operation=uploadFile
37
+ - `binaryPropertyName`: string; required; when resource=storage, operation=uploadFile
38
+ - `upsert`: boolean; optional; when resource=storage, operation=uploadFile
39
+ - `bucket`: string; required; when resource=storage, operation=downloadFile
40
+ - `filePath`: string; required; when resource=storage, operation=downloadFile
41
+ - `binaryPropertyName`: string; required; when resource=storage, operation=downloadFile
42
+ - `bucket`: string; required; when resource=storage, operation=listFiles
43
+ - `folderPath`: string; optional; when resource=storage, operation=listFiles
44
+ - `limit`: number; optional; when resource=storage, operation=listFiles
45
+ - `bucket`: string; required; when resource=storage, operation=deleteFile
46
+ - `filePath`: string; required; when resource=storage, operation=deleteFile
47
+ - `pauseAfterExecution`: boolean; optional
48
+
49
+ ## Example
50
+
51
+ ```ts
52
+ new Step({
53
+ id: 'supabase',
54
+ name: 'supabase',
55
+ type: 'supabase',
56
+ credentials: { name: 'supabase', id: 'credential-id' },
57
+ params: { /* use the required props and conditional values above */ },
58
+ });
59
+ ```
60
+
61
+ Further reading: [Culvii supabase node](https://culvii.com/docs/nodes/supabase/).
@@ -2,7 +2,7 @@
2
2
 
3
3
  - Type ID: `twilio`
4
4
  - Kind: `action`
5
- - Credentials: required as `credentials: { name, id }`
5
+ - Credentials: required as `credentials: { name, id }`; `name` must be one of: `twilio`
6
6
  - Feedback mock: required
7
7
 
8
8
  Resolve the credential through [integration selection](integrations.md); never ask the user to copy a credential ID.
@@ -31,7 +31,7 @@ new Step({
31
31
  id: 'twilio',
32
32
  name: 'twilio',
33
33
  type: 'twilio',
34
- credentials: { name: 'Stored credential', id: 'credential-id' },
34
+ credentials: { name: 'twilio', id: 'credential-id' },
35
35
  params: { /* use the required props and conditional values above */ },
36
36
  });
37
37
  ```
@@ -2,26 +2,50 @@
2
2
 
3
3
  Generated from `GENERATED_NODE_DEFINITIONS`. Open the exact node page before authoring its params.
4
4
 
5
+ - [`argocd`](node-argocd.md) — action; credentials required; feedback mock required
6
+ - [`clickupDoc`](node-clickup-doc.md) — action; credentials required; feedback mock required
7
+ - [`clickupTicket`](node-clickup-ticket.md) — action; credentials required; feedback mock required
5
8
  - [`core.agent`](node-core-agent.md) — action
6
9
  - [`core.browserAutomation`](node-core-browser-automation.md) — action; feedback mock required
7
10
  - [`core.code`](node-core-code.md) — action
8
11
  - [`core.http`](node-core-http.md) — action; feedback mock required
9
12
  - [`core.if`](node-core-if.md) — action
10
13
  - [`core.jwt`](node-core-jwt.md) — action
14
+ - [`core.loop`](node-core-loop.md) — action
15
+ - [`core.loopBreak`](node-core-loop-break.md) — action
16
+ - [`core.loopContinue`](node-core-loop-continue.md) — action
17
+ - [`core.loopOutput`](node-core-loop-output.md) — action
18
+ - [`core.merge`](node-core-merge.md) — action
11
19
  - [`core.set`](node-core-set.md) — action
20
+ - [`core.switch`](node-core-switch.md) — action
21
+ - [`costExplorer`](node-cost-explorer.md) — action; credentials required; feedback mock required
12
22
  - [`cronTrigger`](node-cron-trigger.md) — trigger
13
23
  - [`elasticsearch`](node-elasticsearch.md) — action; credentials required; feedback mock required
24
+ - [`github`](node-github.md) — action; credentials required; feedback mock required
25
+ - [`githubPollTrigger`](node-github-poll-trigger.md) — trigger; credentials required; feedback mock required
26
+ - [`githubWebhookTrigger`](node-github-webhook-trigger.md) — trigger; credentials required; feedback mock required
14
27
  - [`gmail`](node-gmail.md) — action; credentials required; feedback mock required
15
28
  - [`gmailTrigger`](node-gmail-trigger.md) — trigger; credentials required; feedback mock required
16
29
  - [`googleCalendar`](node-google-calendar.md) — action; credentials required; feedback mock required
17
30
  - [`googleDocs`](node-google-docs.md) — action; credentials required; feedback mock required
31
+ - [`grafanaDashboard`](node-grafana-dashboard.md) — action; credentials required; feedback mock required
32
+ - [`grafanaDataSource`](node-grafana-data-source.md) — action; credentials required; feedback mock required
33
+ - [`grafanaQuery`](node-grafana-query.md) — action; credentials required; feedback mock required
34
+ - [`hibp.listDomains`](node-hibp-list-domains.md) — action; credentials required; feedback mock required
35
+ - [`hibp.stealerLogs`](node-hibp-stealer-logs.md) — action; credentials required; feedback mock required
36
+ - [`kubernetes`](node-kubernetes.md) — action; credentials required; feedback mock required
18
37
  - [`manualTrigger`](node-manual-trigger.md) — trigger
19
38
  - [`microsoftOutlook`](node-microsoft-outlook.md) — action; credentials required; feedback mock required
20
39
  - [`microsoftOutlookTrigger`](node-microsoft-outlook-trigger.md) — trigger; credentials required; feedback mock required
21
40
  - [`microsoftSharepoint`](node-microsoft-sharepoint.md) — action; credentials required; feedback mock required
41
+ - [`onionsearch`](node-onionsearch.md) — action; credentials required; feedback mock required
42
+ - [`prometheus`](node-prometheus.md) — action; credentials required; feedback mock required
22
43
  - [`s3`](node-s3.md) — action; credentials required; feedback mock required
23
44
  - [`slack`](node-slack.md) — action; credentials required; feedback mock required
45
+ - [`slackEventsTrigger`](node-slack-events-trigger.md) — trigger; credentials required; feedback mock required
46
+ - [`slackInteractionsTrigger`](node-slack-interactions-trigger.md) — trigger; credentials required; feedback mock required
24
47
  - [`slackTrigger`](node-slack-trigger.md) — trigger; credentials required; feedback mock required
48
+ - [`supabase`](node-supabase.md) — action; credentials required; feedback mock required
25
49
  - [`twilio`](node-twilio.md) — action; credentials required; feedback mock required
26
50
  - [`waitTimer`](node-wait-timer.md) — action
27
51
  - [`webhookTrigger`](node-webhook-trigger.md) — trigger
@@ -7,7 +7,18 @@ For workflow-attached surfaces, make selection, validation, preview, and approva
7
7
  - Objects: `KeyValue`; wrap important groups in `Card` or `Section`.
8
8
  - Arrays: `Table` for comparable records, or repeated domain cards composed with layout components.
9
9
  - Metrics: `Stat`, `Money`, `Duration`, or `Timestamp`.
10
- - Files: `FileChip` bound through `$binary`.
10
+ - Files: `FileChip` bound through `$binary`. Binding `file` alone renders a read-only file
11
+ summary — it is NOT clickable until you also declare `actions.default` as a `navigate` action
12
+ whose `href` points at the same descriptor's `downloadUrl`:
13
+ ```ts
14
+ {
15
+ id: 'file', type: 'FileChip',
16
+ props: { file: { path: '/$binary/Render Report/main/0/0/report' } },
17
+ actions: {
18
+ default: { type: 'navigate', href: { path: '/$binary/Render Report/main/0/0/report/downloadUrl' } },
19
+ },
20
+ }
21
+ ```
11
22
  - Human decisions: a wait `Form` with input components and `Button`, or `ApproveRejectBar`.
12
23
  - Raw/debug values: `JsonInspector` or `Code`.
13
24
 
@@ -129,7 +129,7 @@ Props:
129
129
 
130
130
  ## FileChip
131
131
 
132
- Metadata and download affordance for a produced file.
132
+ Metadata and download affordance for a produced file. Binding `file` alone does not make the chip clickable — declare `actions.default` as a `navigate` action with `href` bound to the same descriptor's `downloadUrl` path (e.g. `{ path: "/$binary/<step>/main/0/0/<key>/downloadUrl" }`), or the chip renders as a read-only file summary with no download button.
133
133
 
134
134
  - Children: `none`
135
135
  - Interaction: `single-action`
@@ -1,41 +1,38 @@
1
1
  # Surface configuration and visual approval
2
2
 
3
- Use this flow for every newly authored workflow. The agent authors surfaces; the user chooses the experience and approves what they see.
3
+ Use this flow for every newly authored workflow. The agent authors surfaces; the user reviews the exact Culvii renderer before accepting them.
4
4
 
5
5
  ## Choose before validation
6
6
 
7
- 1. After planning the workflow graph and expected node data, ask once through the agent's native in-run question tool whether the user wants to configure runtime widgets or keep the defaults. Do not end the chat run to ask.
8
- 2. If the user chooses configuration, ask for each node in each workflow whether to:
9
- - create a custom surface now;
10
- - attach a compatible existing surface; or
11
- - use the platform default.
12
- 3. Present only real existing surfaces found in project files or command output. Never invent a surface reference. Combine independent node choices into the fewest question-tool prompts the agent supports.
13
- 4. Read [surface authoring](surface-authoring.md) and only the component catalog pages needed for custom choices. Use expected output shape and the workflow's purpose to design the surface; do not ask the user to write component documents.
14
- 5. Create every custom candidate as a real Culvii `Surface` and attach it to its workflow step before the first `culvii dev`. "Candidate" describes its approval state, not a separate resource type. Attach selected existing surfaces now and leave default choices unchanged.
7
+ 1. After planning the workflow graph and expected node data, ask once through the agent's native in-run question tool whether the user wants runtime widgets or platform defaults. Do not end the chat run to ask.
8
+ 2. If the user chooses configuration, ask for each node in each workflow whether to create a custom surface, attach a real existing surface, or use the default. Combine independent choices into the fewest prompts the agent supports.
9
+ 3. Read [surface authoring](surface-authoring.md) and only the component catalog pages needed for custom choices. Use expected output shape and workflow purpose; do not ask the user to write component documents.
10
+ 4. Create every custom candidate as a real Culvii `Surface` and attach it to its workflow step before the first `culvii dev`. Attach selected existing surfaces now and leave default choices unchanged.
15
11
 
16
- Do not introduce a wait surface or pause merely to display output. A wait surface is valid only when the requested workflow already requires human input. Surface documents use only supported Culvii components and bindings; the temporary preview HTML described below is never placed in a `.culvii.ts` file.
12
+ Do not add a wait surface or pause merely to display output. A wait surface is valid only when the workflow already needs human input.
17
13
 
18
- ## Validate and collect data
14
+ ## Validate, execute, and review
19
15
 
20
- Start one tracked `culvii dev` process after the workflow and all candidate surfaces exist. Fix every schema, prop, binding, slot, and cross-resource error reported by the watcher. Never preview an invalid candidate.
16
+ 1. Start one tracked `culvii dev` process after the workflow and all candidate surfaces exist. Fix every validation and sync error before previewing.
17
+ 2. Run the [workflow feedback cycle](feedback-cycle.md). Its successful execution supplies the preview data. For a cron, webhook, or polling trigger, use its temporary manual-trigger conversion and representative payload; never invoke or mock the runtime trigger implementation.
18
+ 3. For every custom surface in that execution, create a review manifest. It includes only the configured nodes, never the full run:
21
19
 
22
- Once the draft graph syncs successfully, run the [workflow feedback cycle](feedback-cycle.md). Use its successful node outputs as preview data. For an authored cron, webhook, or polling trigger, create a representative payload matching its real output shape and deliver it through the temporary manual-trigger conversion. This supplies the trigger's surface and downstream nodes without mocking or invoking the runtime trigger implementation. Sanitize private values and replace credentials, tokens, raw binary, and other secrets with harmless representative values.
20
+ ```json
21
+ {
22
+ "items": [
23
+ { "executionId": "exc_…", "nodeId": "research-agent" },
24
+ { "executionId": "exc_…", "nodeId": "report-output" }
25
+ ]
26
+ }
27
+ ```
23
28
 
24
- ## Visual approval loop
29
+ 4. Run `culvii surface review create --file <manifest.json> --json`. It returns a Console URL. Ask permission before running `culvii surface review open <review-id>`; otherwise show the URL to the user and keep the same chat run open.
30
+ 5. The review page uses the production `SurfaceView` renderer, groups items by workflow, and labels each preview as **Mocked output**, **Simulated trigger**, or **Executed output**. It shows only the configured custom surfaces.
31
+ 6. Wait for the user to choose **Keep this surface**, **Request changes**, or **Use default** for every item and submit the review. Read `culvii surface review get <review-id> --json` to obtain the decisions; do not ask the user to paste them into chat.
32
+ 7. For changes, edit the real surface and let the active `culvii dev` watcher validate/sync it. Create a new review after the next successful feedback execution. For default, remove the custom attachment/resource as appropriate and let `culvii dev` validate it.
25
33
 
26
- For each custom candidate:
27
-
28
- 1. Create a tracked temporary directory outside the project and generate a self-contained HTML file that approximates the validated Culvii surface with its sanitized execution data. Use inline CSS and only minimal local JavaScript needed for visual interaction. Make no network requests. Escape untrusted text, do not embed credentials or raw binary, and label the page **Visual preview — Culvii runtime rendering may differ**.
29
- 2. Ask for permission before launching the local `file://` page in the user's browser. If the environment cannot open it, provide the local file path and keep the same chat run waiting for review; do not treat the surface as approved.
30
- 3. Ask through the native in-run question tool:
31
- - **Keep this widget** — accept the attached custom surface;
32
- - **Change it** — collect plain-language feedback in the same run; or
33
- - **Use the default** — detach/remove the candidate and keep the platform default.
34
- 4. For **Change it**, edit the real surface, wait for the active `culvii dev` watcher to validate and sync it, regenerate the HTML with the same data, and ask again. Never show a revision that failed validation.
35
- 5. For **Use the default**, remove the custom attachment/resource as appropriate and wait for `culvii dev` to validate the updated graph.
36
-
37
- The HTML is a review aid, not a second validator and not a claim of pixel parity with the Culvii runtime. Component contracts and bindings remain authoritative through `culvii dev`.
34
+ The review is an ephemeral, user-scoped record. It resolves the current draft surface and current execution data on each page load, so it never claims that an old preview matches a revised surface. It expires after two hours; recreate it if needed.
38
35
 
39
36
  ## Finish
40
37
 
41
- Every node must end as accepted custom, selected existing, platform default, or explicitly skipped by the user. After the final workflow execution succeeds, delete only the tracked temporary preview directory and follow the development guide to stop the exact `culvii dev` process. Never report completion while a custom surface is awaiting review.
38
+ Every configured node must end as accepted custom, selected existing, platform default, or explicitly skipped. Restore any temporary trigger conversion, wait for `culvii dev` to sync it, then stop only the exact `culvii dev` process started for this task. Never report completion while a custom surface is awaiting review.