@sellable/mcp 0.1.5 → 0.1.6

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/README.md CHANGED
@@ -80,50 +80,33 @@ The token is provided when you generate it. Use `list_workspaces` +
80
80
 
81
81
  ### 4. Codex Setup
82
82
 
83
- For customer/package installs, use:
83
+ For customer/package installs, use the public installer:
84
84
 
85
85
  ```bash
86
- npx -y @sellable/install --host codex --token skt_live_your_token_here --workspace-id your_workspace_id
86
+ npx -y @sellable/install@0.1.6 --host codex --token skt_live_your_token_here --workspace-id your_workspace_id
87
87
  ```
88
88
 
89
- For local repo/Desktop development, run the installer from this repo:
89
+ If you already have `~/.sellable/config.json`, rerun/verify without rewriting
90
+ auth:
90
91
 
91
92
  ```bash
92
- npm run sellable:codex:install -- --token skt_live_your_token_here --workspace-id your_workspace_id
93
+ npx -y @sellable/install@0.1.6 --host codex
94
+ sellable --verify-only --host codex
93
95
  ```
94
96
 
95
97
  The installer does the full local setup:
96
98
 
97
- - builds the Sellable MCP server
98
- - uses repo-local `web` skills by default, so the Codex picker has one Sellable
99
- entry per workflow
100
- - removes stale Personal Sellable skill copies, including
101
- `sellable-create-campaign-v2`
102
99
  - writes `~/.sellable/config.json`
103
100
  - registers the `sellable` MCP server with Codex
104
- - installs the local `sellable@sellable-local` Desktop plugin so Codex
105
- Desktop loads the `mcp__sellable__*` tools into skill sessions
106
- - runs a Codex CLI smoke that must load `get_auth_status` and the
107
- `create-campaign-v2` prompt
108
-
109
- If you already have `~/.sellable/config.json`, verify the install without
110
- rewriting auth:
111
-
112
- ```bash
113
- npm run sellable:codex:install -- --verify-only
114
- ```
115
-
116
- For published-package installs instead of this local checkout:
117
-
118
- ```bash
119
- npm run sellable:codex:install -- --server-mode package --skill-scope personal --token skt_live_your_token_here --workspace-id your_workspace_id
120
- ```
101
+ - installs the `sellable@sellable` Desktop plugin so Codex Desktop loads the
102
+ `mcp__sellable__*` tools into skill sessions
121
103
 
122
104
  After the installer passes, fully quit and reopen Codex Desktop. Start a new
123
- thread from the repo and select the `web` `Sellable Create Campaign` entry. If
124
- the app still says `mcp__sellable__*` tools are missing after the installer
125
- passes, check that `~/.codex/config.toml` contains both
126
- `[marketplaces.sellable-local]` and `[plugins."sellable@sellable-local"]`.
105
+ thread and select `Sellable Create Campaign`, or invoke
106
+ `$sellable:create-campaign`. If the app still says
107
+ `mcp__sellable__*` tools are missing after the installer passes, check that
108
+ `~/.codex/config.toml` contains both `[marketplaces.sellable]` and
109
+ `[plugins."sellable@sellable"]`.
127
110
  The skill being visible only proves skill discovery; the plugin is what mounts
128
111
  the Sellable MCP tools for Codex Desktop.
129
112
 
@@ -164,9 +147,9 @@ Use the Codex skill entrypoint:
164
147
  $sellable:create-campaign
165
148
  ```
166
149
 
167
- Skill package path in this repo:
150
+ Installed skill package path:
168
151
 
169
- - `.agents/skills/sellable-create-campaign/SKILL.md`
152
+ - `~/.codex/plugins/cache/sellable/sellable/<version>/skills/sellable-create-campaign/SKILL.md`
170
153
 
171
154
  ## Host Parity Runbook (Codex + Claude)
172
155
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sellable/mcp",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "type": "module",
5
5
  "description": "Sellable MCP server for Claude Code and Codex campaign workflows",
6
6
  "main": "dist/index.js",
@@ -74,20 +74,27 @@ Validated draft directory:
74
74
  - Net-new runs start at `bootstrap` -> `brief-interview` in
75
75
  `core/flow.v2.json`. Do not start at `validate-artifacts` unless resuming a
76
76
  compatibility run where all upstream artifacts already exist.
77
+ - Use the host-native structured question gate whenever it is exposed. In
78
+ Claude Code, this is `AskUserQuestion`. In Codex, this is
79
+ `request_user_input`. Treat them as equivalent approval/intake gates and
80
+ persist the same draft artifacts after the user answers. If the session is
81
+ non-interactive or the host does not expose either structured question tool,
82
+ fall back to a normal chat question with the exact same choices and make the
83
+ fallback explicit to the user.
77
84
  - Fast Intake Mode is mandatory for hosted/rehearsal net-new runs. Ask the
78
85
  first founder strategy/source question packet in under 60 seconds. Before
79
86
  that first packet, the first assistant turn may only call
80
87
  `bootstrap_create_campaign`, load this workflow prompt with
81
88
  `get_subskill_prompt({ subskillName: "create-campaign-v2" })`, optionally run
82
- one lightweight identity lookup, then call `AskUserQuestion`. If the user
89
+ one lightweight identity lookup, then use the structured question gate. If the user
83
90
  supplied a company website/domain, call exactly one of `fetch_company`,
84
91
  `WebFetch`, or `WebSearch` to identify what the company actually does before
85
92
  generating intake options. If the user supplied a LinkedIn profile URL, call
86
93
  `fetch_linkedin_profile` before generating intake options. Do not infer the
87
94
  product category from the company name alone. If no domain, website, or
88
95
  LinkedIn profile is supplied, use neutral/custom intake options rather than
89
- guessed vertical-specific options. Before the first AskUserQuestion, do not run
90
- sender research, `list_senders`, source discovery, Sales Nav, Prospeo,
96
+ guessed vertical-specific options. Before the first structured question gate,
97
+ do not run sender research, `list_senders`, source discovery, Sales Nav, Prospeo,
91
98
  Signals, Bash, Read, Write, Edit, Glob, Grep, full company research, or
92
99
  draft-directory inspection/creation. Do draft-directory setup only after the
93
100
  founder answers. The first intake packet must ask buyer, offer/CTA, proof, and
@@ -199,9 +206,9 @@ There are two human gates:
199
206
  Earlier artifact gates are interrupt-only unless this contract explicitly
200
207
  names the `message-review` gate.
201
208
 
202
- Auto-continue without `AskUserQuestion` when the artifact says `Status:
203
- confirmed` (or equivalent), confidence is high/medium, volume is viable, and
204
- there is no strategic tradeoff.
209
+ Auto-continue without a structured question gate when the artifact says
210
+ `Status: confirmed` (or equivalent), confidence is high/medium, volume is
211
+ viable, and there is no strategic tradeoff.
205
212
 
206
213
  Ask the user only when one of these is true:
207
214
 
@@ -688,9 +695,9 @@ or tone feedback you want before I build the approval packet.` Do not write
688
695
  The next Codex UAT goal is to prove message quality before mint, so no
689
696
  approval packet or campaign mutation should happen just because the mechanics
690
697
  are working.
691
- - immediately after rendering `message-review.md`, call `AskUserQuestion` with
692
- exactly two choices, in this order: `approve-message`, `revise-messaging`.
693
- Stop after the question. Do not write `approval-packet.md`,
698
+ - immediately after rendering `message-review.md`, use the structured question
699
+ gate with exactly two choices, in this order: `approve-message`,
700
+ `revise-messaging`. Stop after the question. Do not write `approval-packet.md`,
694
701
  `customer-roleplay.md`, or a commit-gate question until
695
702
  `message-review-decision.md` contains `approve-message`.
696
703
  - if the selected winner or PS uses named customer/logo proof, quantified proof,
@@ -821,7 +828,7 @@ Do not:
821
828
  invitation to give manual feedback before approval
822
829
  - `Question: approve-message or revise-messaging?`
823
830
  - `Recommendation:` exactly `approve-message` or `revise-messaging`
824
- - The two-choice `AskUserQuestion` immediately after the rendered review
831
+ - The two-choice structured question gate immediately after the rendered review
825
832
 
826
833
  `message-review-decision.md` must contain exactly one selected route:
827
834
  `approve-message` or `revise-messaging`. It does not authorize DB mutation.
@@ -956,15 +963,17 @@ anchors at the user.
956
963
 
957
964
  When rendering the approval packet inline, start it with exactly
958
965
  `Status: approval-packet`. Write the same content to `approval-packet.md`
959
- before showing the gate. The same assistant turn must then call
960
- `AskUserQuestion` with the six commit choices below. A commit-gate question
961
- without the inline `Status: approval-packet` packet is invalid UX. If a
966
+ before showing the gate. The same assistant turn must then use the structured
967
+ question gate with the six commit choices below. In Claude Code, call
968
+ `AskUserQuestion`; in Codex, call `request_user_input` when available. A
969
+ commit-gate question without the inline `Status: approval-packet` packet is
970
+ invalid UX. If a
962
971
  customer roleplay is performed, write `customer-roleplay.md` before the final
963
972
  choice. A roleplay result that says "looks good", "approve", or equivalent is
964
973
  only critique; it does not satisfy the gate. Write `commit-gate-decision.md`
965
974
  only after the user/operator makes one explicit choice.
966
975
 
967
- Use `AskUserQuestion` with exactly these 6 choices, in this order:
976
+ Use the structured question gate with exactly these 6 choices, in this order:
968
977
 
969
978
  ```text
970
979
  approve
@@ -1329,6 +1338,33 @@ atomic mint).
1329
1338
  > `search_prospeo`, `search_sales_nav`, `search_apollo`,
1330
1339
  > `search_signals`, and any other provider search tool added later.
1331
1340
  > Campaignless searches after mint orphan results from the campaign UI.
1341
+ >
1342
+ > **Lead-list vs campaign-table identity rule (do not confuse them):**
1343
+ > after the first `confirm_lead_list`, two workflow tables exist:
1344
+ >
1345
+ > - the **lead-list** table (the original `sourceLeadListId` returned by
1346
+ > `import_leads`), and
1347
+ > - the **campaign workflow table** (`CampaignOffer.workflowTableId`,
1348
+ > also returned as `campaignTableId` from `confirm_lead_list`).
1349
+ >
1350
+ > `confirm_lead_list` overwrites `CampaignOffer.selectedLeadListId` with
1351
+ > the campaign-table id. That means after the first confirm, the
1352
+ > campaign-table id is NOT a valid `sourceLeadListId` for any future
1353
+ > `import_leads` call.
1354
+ >
1355
+ > When you scale up the import, `mode: "add"` requires the ORIGINAL
1356
+ > lead-list id (the one returned by the first `import_leads`), never the
1357
+ > campaign-table id. Passing the campaign-table id silently writes
1358
+ > straight into the campaign workflow table, bypassing the lead list
1359
+ > entirely; the lead list stays at its original size and the
1360
+ > campaign-builder `/leads` UI throws "Lead list not found" because it
1361
+ > expects `selectedLeadListId` to resolve as a lead list.
1362
+ >
1363
+ > Capture the original `leadListId` from the FIRST `import_leads`
1364
+ > response and reuse it for every scale-up `import_leads(mode: "add")`
1365
+ > call on the same campaign. If the original id is unknown, query
1366
+ > for the lead-list table by name or skip the `mode: "add"` path; do
1367
+ > not pass the campaign-table id as `sourceLeadListId`.
1332
1368
 
1333
1369
  1. Load `core/auto-execute.yaml`. Capture `import.importLimit`,
1334
1370
  `sample.sampleSize`, `sample.minProjectedPass`,
@@ -73,7 +73,8 @@
73
73
  "get_auth_status",
74
74
  "get_active_workspace",
75
75
  "get_subskill_prompt",
76
- "AskUserQuestion"
76
+ "AskUserQuestion",
77
+ "request_user_input"
77
78
  ],
78
79
  "doNotAllow": [
79
80
  "create_campaign",
@@ -155,10 +156,7 @@
155
156
  }
156
157
  ],
157
158
  "requiredArtifacts": [],
158
- "producesArtifacts": [
159
- "brief-v1.md",
160
- "brief.md"
161
- ],
159
+ "producesArtifacts": ["brief-v1.md", "brief.md"],
162
160
  "allowedTools": [
163
161
  "get_subskill_prompt",
164
162
  "get_auth_status",
@@ -171,7 +169,8 @@
171
169
  "fetch_linkedin_posts",
172
170
  "WebFetch",
173
171
  "WebSearch",
174
- "AskUserQuestion"
172
+ "AskUserQuestion",
173
+ "request_user_input"
175
174
  ],
176
175
  "doNotAllow": [
177
176
  "create_campaign",
@@ -183,17 +182,12 @@
183
182
  "start_campaign"
184
183
  ],
185
184
  "watchRequired": false,
186
- "waitFor": [
187
- "brief_v1_ready",
188
- "confirm_with_user"
189
- ],
185
+ "waitFor": ["brief_v1_ready", "confirm_with_user"],
190
186
  "transitions": {
191
187
  "brief_v1_ready": "brief-review",
192
188
  "confirm_with_user": "brief-review"
193
189
  },
194
- "optionalProducesArtifacts": [
195
- "lead-source-intake.json"
196
- ]
190
+ "optionalProducesArtifacts": ["lead-source-intake.json"]
197
191
  },
198
192
  {
199
193
  "id": "brief-review",
@@ -216,22 +210,17 @@
216
210
  "action": "ask_continue_or_revise_only_if_needed",
217
211
  "autoContinueWhen": {
218
212
  "artifactStatus": "confirmed",
219
- "confidenceIn": [
220
- "high",
221
- "medium"
222
- ],
213
+ "confidenceIn": ["high", "medium"],
223
214
  "noOpenStrategicTradeoff": true,
224
215
  "noMissingRequiredInputs": true
225
216
  }
226
217
  }
227
218
  ],
228
- "requiredArtifacts": [
229
- "brief-v1.md",
230
- "brief.md"
231
- ],
219
+ "requiredArtifacts": ["brief-v1.md", "brief.md"],
232
220
  "producesArtifacts": [],
233
221
  "allowedTools": [
234
222
  "AskUserQuestion",
223
+ "request_user_input",
235
224
  "get_subskill_prompt"
236
225
  ],
237
226
  "doNotAllow": [
@@ -244,11 +233,7 @@
244
233
  "start_campaign"
245
234
  ],
246
235
  "watchRequired": false,
247
- "waitFor": [
248
- "user_brief_confirmed",
249
- "revise_brief",
250
- "auto_continue"
251
- ],
236
+ "waitFor": ["user_brief_confirmed", "revise_brief", "auto_continue"],
252
237
  "transitions": {
253
238
  "user_brief_confirmed": "find-leads",
254
239
  "revise_brief": "brief-interview",
@@ -292,20 +277,11 @@
292
277
  },
293
278
  {
294
279
  "action": "write_artifacts",
295
- "artifacts": [
296
- "lead-review.md",
297
- "lead-sample.json"
298
- ]
280
+ "artifacts": ["lead-review.md", "lead-sample.json"]
299
281
  }
300
282
  ],
301
- "requiredArtifacts": [
302
- "brief-v1.md",
303
- "brief.md"
304
- ],
305
- "producesArtifacts": [
306
- "lead-review.md",
307
- "lead-sample.json"
308
- ],
283
+ "requiredArtifacts": ["brief-v1.md", "brief.md"],
284
+ "producesArtifacts": ["lead-review.md", "lead-sample.json"],
309
285
  "allowedTools": [
310
286
  "get_subskill_prompt",
311
287
  "get_provider_prompt",
@@ -317,6 +293,7 @@
317
293
  "fetch_company",
318
294
  "fetch_linkedin_profile",
319
295
  "AskUserQuestion",
296
+ "request_user_input",
320
297
  "load_csv_linkedin_leads",
321
298
  "load_csv_domains",
322
299
  "get_rows_minimal"
@@ -331,19 +308,13 @@
331
308
  "start_campaign"
332
309
  ],
333
310
  "watchRequired": false,
334
- "waitFor": [
335
- "lead_review_ready",
336
- "revise_brief",
337
- "confirm_with_user"
338
- ],
311
+ "waitFor": ["lead_review_ready", "revise_brief", "confirm_with_user"],
339
312
  "transitions": {
340
313
  "lead_review_ready": "lead-review",
341
314
  "revise_brief": "brief-interview",
342
315
  "confirm_with_user": "lead-review"
343
316
  },
344
- "optionalRequiredArtifacts": [
345
- "lead-source-intake.json"
346
- ],
317
+ "optionalRequiredArtifacts": ["lead-source-intake.json"],
347
318
  "toolRules": {
348
319
  "suppliedLinkedinProfiles": "Preview only before approval: call load_csv_linkedin_leads without confirmed, campaignOfferId, currentStep, leadListId, sourceLeadListId, or provider-import parameters; skip provider discovery.",
349
320
  "suppliedDomains": "May confirm load_csv_domains before approval only without campaignOfferId/currentStep to produce a standalone domainFilterId, then run a campaignless Prospeo sample constrained by domainFilterId.",
@@ -404,10 +375,7 @@
404
375
  "action": "ask_continue_revise_or_confirm_only_if_needed",
405
376
  "autoContinueWhen": {
406
377
  "status": "confirmed",
407
- "confidenceIn": [
408
- "high",
409
- "medium"
410
- ],
378
+ "confidenceIn": ["high", "medium"],
411
379
  "projectedGoodFitsAtLeast": 150,
412
380
  "samplePassRateAtLeast": 0.7,
413
381
  "noProviderMismatch": true,
@@ -415,13 +383,11 @@
415
383
  }
416
384
  }
417
385
  ],
418
- "requiredArtifacts": [
419
- "lead-review.md",
420
- "lead-sample.json"
421
- ],
386
+ "requiredArtifacts": ["lead-review.md", "lead-sample.json"],
422
387
  "producesArtifacts": [],
423
388
  "allowedTools": [
424
389
  "AskUserQuestion",
390
+ "request_user_input",
425
391
  "get_subskill_prompt"
426
392
  ],
427
393
  "doNotAllow": [
@@ -455,49 +421,31 @@
455
421
  {
456
422
  "action": "run_stage",
457
423
  "target": "filter-leads",
458
- "inputs": [
459
- "brief.md",
460
- "lead-review.md",
461
- "lead-sample.json"
462
- ]
424
+ "inputs": ["brief.md", "lead-review.md", "lead-sample.json"]
463
425
  },
464
426
  {
465
427
  "action": "write_artifacts",
466
- "artifacts": [
467
- "lead-filter.md"
468
- ],
469
- "optionalArtifacts": [
470
- "rubric.json"
471
- ]
428
+ "artifacts": ["lead-filter.md"],
429
+ "optionalArtifacts": ["rubric.json"]
472
430
  },
473
431
  {
474
432
  "action": "ask_revise_only_if_filter_is_not_confirmed",
475
433
  "autoContinueWhen": {
476
434
  "status": "confirmed",
477
- "decisionIn": [
478
- "continue",
479
- "confirmed"
480
- ],
435
+ "decisionIn": ["continue", "confirmed"],
481
436
  "expectedUsableLeadsAtLeast": 150,
482
437
  "noHeavyFilteringWarning": true,
483
438
  "noCampaignMissRisk": true
484
439
  }
485
440
  }
486
441
  ],
487
- "requiredArtifacts": [
488
- "brief.md",
489
- "lead-review.md",
490
- "lead-sample.json"
491
- ],
492
- "producesArtifacts": [
493
- "lead-filter.md"
494
- ],
495
- "optionalProducesArtifacts": [
496
- "rubric.json"
497
- ],
442
+ "requiredArtifacts": ["brief.md", "lead-review.md", "lead-sample.json"],
443
+ "producesArtifacts": ["lead-filter.md"],
444
+ "optionalProducesArtifacts": ["rubric.json"],
498
445
  "allowedTools": [
499
446
  "get_subskill_prompt",
500
- "AskUserQuestion"
447
+ "AskUserQuestion",
448
+ "request_user_input"
501
449
  ],
502
450
  "doNotAllow": [
503
451
  "create_campaign",
@@ -543,17 +491,12 @@
543
491
  "artifact": "message-validation.md"
544
492
  }
545
493
  ],
546
- "requiredArtifacts": [
547
- "brief.md",
548
- "lead-review.md",
549
- "lead-sample.json"
550
- ],
551
- "producesArtifacts": [
552
- "message-validation.md"
553
- ],
494
+ "requiredArtifacts": ["brief.md", "lead-review.md", "lead-sample.json"],
495
+ "producesArtifacts": ["message-validation.md"],
554
496
  "allowedTools": [
555
497
  "get_subskill_prompt",
556
- "AskUserQuestion"
498
+ "AskUserQuestion",
499
+ "request_user_input"
557
500
  ],
558
501
  "toolRules": [
559
502
  "Before writing message-validation.md, message-review.md, approval-packet.md, or a commit-gate AskUserQuestion, the current run must read 100% of the real generate-messages prompt via chunked get_subskill_prompt({ subskillName: \"generate-messages\", offset, limit }) calls.",
@@ -608,10 +551,7 @@
608
551
  "lead-filter.md",
609
552
  "message-validation.md"
610
553
  ],
611
- "optionalFiles": [
612
- "message-prep.md",
613
- "message-candidate-drafts.md"
614
- ]
554
+ "optionalFiles": ["message-prep.md", "message-candidate-drafts.md"]
615
555
  },
616
556
  {
617
557
  "action": "write_message_review",
@@ -639,10 +579,7 @@
639
579
  "Question: approve-message or revise-messaging?",
640
580
  "Recommendation:"
641
581
  ],
642
- "allowedRecommendations": [
643
- "approve-message",
644
- "revise-messaging"
645
- ],
582
+ "allowedRecommendations": ["approve-message", "revise-messaging"],
646
583
  "judgeAgainst": [
647
584
  "generate-messages rules",
648
585
  "gold-standard-* references",
@@ -666,19 +603,13 @@
666
603
  },
667
604
  {
668
605
  "action": "ask_message_review_choice",
669
- "choices": [
670
- "approve-message",
671
- "revise-messaging"
672
- ],
606
+ "choices": ["approve-message", "revise-messaging"],
673
607
  "stopAfterQuestion": true
674
608
  },
675
609
  {
676
610
  "action": "write_message_review_decision",
677
611
  "artifact": "message-review-decision.md",
678
- "allowedChoices": [
679
- "approve-message",
680
- "revise-messaging"
681
- ],
612
+ "allowedChoices": ["approve-message", "revise-messaging"],
682
613
  "doesNotAuthorizeMint": true
683
614
  },
684
615
  {
@@ -694,12 +625,10 @@
694
625
  "lead-filter.md",
695
626
  "message-validation.md"
696
627
  ],
697
- "producesArtifacts": [
698
- "message-review.md",
699
- "message-review-decision.md"
700
- ],
628
+ "producesArtifacts": ["message-review.md", "message-review-decision.md"],
701
629
  "allowedTools": [
702
630
  "AskUserQuestion",
631
+ "request_user_input",
703
632
  "get_subskill_prompt"
704
633
  ],
705
634
  "doNotAllow": [
@@ -712,10 +641,7 @@
712
641
  "start_campaign"
713
642
  ],
714
643
  "watchRequired": false,
715
- "waitFor": [
716
- "message_approved",
717
- "revise_messaging"
718
- ],
644
+ "waitFor": ["message_approved", "revise_messaging"],
719
645
  "transitions": {
720
646
  "message_approved": "approval-packet",
721
647
  "revise_messaging": "message-generation"
@@ -739,9 +665,7 @@
739
665
  "message-review.md",
740
666
  "message-review-decision.md"
741
667
  ],
742
- "optionalFiles": [
743
- "rubric.json"
744
- ]
668
+ "optionalFiles": ["rubric.json"]
745
669
  },
746
670
  {
747
671
  "action": "require_message_review_decision",
@@ -763,11 +687,7 @@
763
687
  "risks and next action"
764
688
  ],
765
689
  "userFacing": true,
766
- "doNotUseWords": [
767
- "anchor",
768
- "validation anchor",
769
- "lane"
770
- ]
690
+ "doNotUseWords": ["anchor", "validation anchor", "lane"]
771
691
  },
772
692
  {
773
693
  "action": "optional_customer_roleplay",
@@ -785,14 +705,11 @@
785
705
  "message-review.md",
786
706
  "message-review-decision.md"
787
707
  ],
788
- "producesArtifacts": [
789
- "approval-packet.md"
790
- ],
791
- "optionalProducesArtifacts": [
792
- "customer-roleplay.md"
793
- ],
708
+ "producesArtifacts": ["approval-packet.md"],
709
+ "optionalProducesArtifacts": ["customer-roleplay.md"],
794
710
  "allowedTools": [
795
711
  "AskUserQuestion",
712
+ "request_user_input",
796
713
  "get_subskill_prompt"
797
714
  ],
798
715
  "doNotAllow": [
@@ -809,9 +726,7 @@
809
726
  "transitions": {
810
727
  "approval_packet_ready": "commit-gate"
811
728
  },
812
- "optionalRequiredArtifacts": [
813
- "lead-source-intake.json"
814
- ]
729
+ "optionalRequiredArtifacts": ["lead-source-intake.json"]
815
730
  },
816
731
  {
817
732
  "id": "validate-artifacts",
@@ -826,9 +741,7 @@
826
741
  "lead-filter.md",
827
742
  "message-validation.md"
828
743
  ],
829
- "optionalFiles": [
830
- "rubric.json"
831
- ]
744
+ "optionalFiles": ["rubric.json"]
832
745
  },
833
746
  {
834
747
  "action": "validate_anchors",
@@ -841,17 +754,13 @@
841
754
  "doesNotAuthorizeMint": true
842
755
  }
843
756
  ],
844
- "allowedTools": [
845
- "AskUserQuestion"
846
- ],
757
+ "allowedTools": ["AskUserQuestion", "request_user_input"],
847
758
  "watchRequired": false,
848
759
  "waitFor": "artifacts_validated",
849
760
  "transitions": {
850
761
  "artifacts_validated": "approval-packet"
851
762
  },
852
- "optionalRequiredArtifacts": [
853
- "lead-source-intake.json"
854
- ]
763
+ "optionalRequiredArtifacts": ["lead-source-intake.json"]
855
764
  },
856
765
  {
857
766
  "id": "commit-gate",
@@ -899,9 +808,7 @@
899
808
  "onlyApproveAuthorizesMint": true
900
809
  }
901
810
  ],
902
- "allowedTools": [
903
- "AskUserQuestion"
904
- ],
811
+ "allowedTools": ["AskUserQuestion", "request_user_input"],
905
812
  "watchRequired": false,
906
813
  "waitFor": [
907
814
  "user_approved",
@@ -919,9 +826,7 @@
919
826
  "user_revise_messaging": "revise-messaging",
920
827
  "user_abort": "abort"
921
828
  },
922
- "optionalRequiredArtifacts": [
923
- "lead-source-intake.json"
924
- ]
829
+ "optionalRequiredArtifacts": ["lead-source-intake.json"]
925
830
  },
926
831
  {
927
832
  "id": "atomic-mint",
@@ -936,24 +841,16 @@
936
841
  },
937
842
  {
938
843
  "tool": "create_campaign",
939
- "requiredFields": [
940
- "campaignBrief",
941
- "currentStep"
942
- ],
844
+ "requiredFields": ["campaignBrief", "currentStep"],
943
845
  "requiredValues": {
944
846
  "currentStep": "auto-execute-leads"
945
847
  },
946
- "capture": [
947
- "campaignId",
948
- "watchUrl"
949
- ],
848
+ "capture": ["campaignId", "watchUrl"],
950
849
  "onMissingWatchUrl": "recoverable_failure_abort_before_rubric_save"
951
850
  },
952
851
  {
953
852
  "tool": "save_rubrics",
954
- "requiredFields": [
955
- "rubric"
956
- ],
853
+ "requiredFields": ["rubric"],
957
854
  "onFailure": "rollback_or_recoverable_stop"
958
855
  },
959
856
  {
@@ -964,21 +861,17 @@
964
861
  },
965
862
  {
966
863
  "action": "surface_watch_link",
967
- "requires": [
968
- "create_campaign_succeeded",
969
- "save_rubrics_succeeded"
970
- ]
864
+ "requires": ["create_campaign_succeeded", "save_rubrics_succeeded"]
971
865
  }
972
866
  ],
973
867
  "allowedTools": [
974
868
  "bootstrap_create_campaign",
975
869
  "create_campaign",
976
870
  "save_rubrics",
977
- "AskUserQuestion"
978
- ],
979
- "doNotAllow": [
980
- "import_leads"
871
+ "AskUserQuestion",
872
+ "request_user_input"
981
873
  ],
874
+ "doNotAllow": ["import_leads"],
982
875
  "watchRequired": true,
983
876
  "waitFor": "autonomous_tail_started",
984
877
  "transitions": {
@@ -1002,9 +895,7 @@
1002
895
  "target": "85-02"
1003
896
  }
1004
897
  ],
1005
- "allowedTools": [
1006
- "AskUserQuestion"
1007
- ],
898
+ "allowedTools": ["AskUserQuestion", "request_user_input"],
1008
899
  "transitions": {
1009
900
  "autonomous_tail_started": "auto-execute-leads"
1010
901
  }
@@ -1041,10 +932,7 @@
1041
932
  },
1042
933
  {
1043
934
  "tool": "import_leads",
1044
- "requiredFields": [
1045
- "campaignOfferId",
1046
- "targetLeadCount"
1047
- ],
935
+ "requiredFields": ["campaignOfferId", "targetLeadCount"],
1048
936
  "targetLeadCountFromConfig": "import.importLimit",
1049
937
  "onZeroLeads": "escalate_hard_fail",
1050
938
  "modeAddHandshake": {
@@ -1058,19 +946,13 @@
1058
946
  },
1059
947
  {
1060
948
  "tool": "wait_for_lead_list_ready",
1061
- "sourceBranches": [
1062
- "normal-discovery",
1063
- "supplied-domains"
1064
- ],
949
+ "sourceBranches": ["normal-discovery", "supplied-domains"],
1065
950
  "skipWhen": "resolved source branch is supplied-linkedin-profiles or existing-lead-list; direct lead-list branches have no provider import job to wait on and this probe can poison the campaign import status"
1066
951
  },
1067
952
  {
1068
953
  "tool": "confirm_lead_list",
1069
954
  "targetLeadCountFromConfig": "import.importLimit",
1070
- "sourceBranches": [
1071
- "supplied-linkedin-profiles",
1072
- "existing-lead-list"
1073
- ]
955
+ "sourceBranches": ["supplied-linkedin-profiles", "existing-lead-list"]
1074
956
  },
1075
957
  {
1076
958
  "tool": "get_rows_minimal",
@@ -1089,10 +971,7 @@
1089
971
  },
1090
972
  {
1091
973
  "tool": "update_campaign",
1092
- "requiredFields": [
1093
- "campaignId",
1094
- "currentStep"
1095
- ],
974
+ "requiredFields": ["campaignId", "currentStep"],
1096
975
  "requiredValues": {
1097
976
  "currentStep": "validate-sample"
1098
977
  }
@@ -1107,14 +986,13 @@
1107
986
  "wait_for_campaign_table_ready",
1108
987
  "update_campaign",
1109
988
  "AskUserQuestion",
989
+ "request_user_input",
1110
990
  "load_csv_linkedin_leads",
1111
991
  "load_csv_domains",
1112
992
  "get_provider_prompt",
1113
993
  "search_prospeo"
1114
994
  ],
1115
- "doNotAllow": [
1116
- "start_campaign"
1117
- ],
995
+ "doNotAllow": ["start_campaign"],
1118
996
  "watchRequired": true,
1119
997
  "waitFor": "leads_imported",
1120
998
  "transitions": {
@@ -1146,17 +1024,11 @@
1146
1024
  },
1147
1025
  {
1148
1026
  "tool": "wait_for_rubric_results",
1149
- "requiredFields": [
1150
- "targetCount"
1151
- ],
1027
+ "requiredFields": ["targetCount"],
1152
1028
  "targetCountSource": "stats.totalRows_or_imported_batch_count",
1153
1029
  "note": "default targetCount=25 returns ready=true after first 25 completions even when cohort is still pending; always pass cohortSize explicitly (see references/sample-validation-loop.md §Known Tool Behaviors #3)",
1154
1030
  "readVia": "subagent",
1155
- "extractFields": [
1156
- "ready",
1157
- "passRate.completed",
1158
- "stats"
1159
- ],
1031
+ "extractFields": ["ready", "passRate.completed", "stats"],
1160
1032
  "doNotRetain": "rows_payload",
1161
1033
  "contextBloatNote": "25 rows ≈ 67KB; 100 rows ≈ 268KB; use subagent extraction (see references/sample-validation-loop.md §Known Tool Behaviors #2)"
1162
1034
  },
@@ -1182,7 +1054,8 @@
1182
1054
  "wait_for_rubric_results",
1183
1055
  "update_campaign_brief",
1184
1056
  "update_campaign",
1185
- "AskUserQuestion"
1057
+ "AskUserQuestion",
1058
+ "request_user_input"
1186
1059
  ],
1187
1060
  "doNotAllow": [
1188
1061
  "import_leads",
@@ -1198,10 +1071,7 @@
1198
1071
  "wait_for_rubric_results_targetCount_always_explicit"
1199
1072
  ],
1200
1073
  "watchRequired": true,
1201
- "waitFor": [
1202
- "sample_validated",
1203
- "sample_revision_required"
1204
- ],
1074
+ "waitFor": ["sample_validated", "sample_revision_required"],
1205
1075
  "transitions": {
1206
1076
  "sample_validated": "auto-execute-messaging",
1207
1077
  "escalation_triggered": "escalation"
@@ -1283,10 +1153,7 @@
1283
1153
  },
1284
1154
  {
1285
1155
  "tool": "update_campaign",
1286
- "requiredFields": [
1287
- "campaignId",
1288
- "currentStep"
1289
- ],
1156
+ "requiredFields": ["campaignId", "currentStep"],
1290
1157
  "requiredValues": {
1291
1158
  "currentStep": "awaiting-user-greenlight"
1292
1159
  }
@@ -1298,13 +1165,10 @@
1298
1165
  "wait_for_campaign_table_ready",
1299
1166
  "update_campaign_brief",
1300
1167
  "update_campaign",
1301
- "AskUserQuestion"
1302
- ],
1303
- "doNotAllow": [
1304
- "import_leads",
1305
- "start_campaign",
1306
- "generate_messages"
1168
+ "AskUserQuestion",
1169
+ "request_user_input"
1307
1170
  ],
1171
+ "doNotAllow": ["import_leads", "start_campaign", "generate_messages"],
1308
1172
  "hardRules": [
1309
1173
  "critique_failure_never_escalates",
1310
1174
  "critique_sample_size_bounded_by_config",
@@ -1316,10 +1180,7 @@
1316
1180
  "campaign_brief_must_contain_approved_message_template_tokens_before_generate_message_cascade"
1317
1181
  ],
1318
1182
  "watchRequired": true,
1319
- "waitFor": [
1320
- "review_batch_ready",
1321
- "sample_revision_required"
1322
- ],
1183
+ "waitFor": ["review_batch_ready", "sample_revision_required"],
1323
1184
  "transitions": {
1324
1185
  "review_batch_ready": "awaiting-user-greenlight",
1325
1186
  "escalation_triggered": "escalation"
@@ -1336,10 +1197,7 @@
1336
1197
  },
1337
1198
  {
1338
1199
  "action": "surface_watch_link",
1339
- "requires": [
1340
- "create_campaign_succeeded",
1341
- "save_rubrics_succeeded"
1342
- ]
1200
+ "requires": ["create_campaign_succeeded", "save_rubrics_succeeded"]
1343
1201
  },
1344
1202
  {
1345
1203
  "action": "surface_source_materialization_summary",
@@ -1361,25 +1219,18 @@
1361
1219
  ],
1362
1220
  "allowedTools": [
1363
1221
  "attach_recommended_sequence",
1364
- "AskUserQuestion"
1365
- ],
1366
- "doNotAllow": [
1367
- "start_campaign",
1368
- "import_leads"
1222
+ "AskUserQuestion",
1223
+ "request_user_input"
1369
1224
  ],
1225
+ "doNotAllow": ["start_campaign", "import_leads"],
1370
1226
  "autoStart": false,
1371
1227
  "watchRequired": true,
1372
- "waitFor": [
1373
- "user_greenlight",
1374
- "ui_start_detected"
1375
- ],
1228
+ "waitFor": ["user_greenlight", "ui_start_detected"],
1376
1229
  "transitions": {
1377
1230
  "user_greenlight": "claude-greenlight",
1378
1231
  "ui_start_detected": "running"
1379
1232
  },
1380
- "optionalRequiredArtifacts": [
1381
- "lead-source-intake.json"
1382
- ]
1233
+ "optionalRequiredArtifacts": ["lead-source-intake.json"]
1383
1234
  },
1384
1235
  {
1385
1236
  "id": "claude-greenlight",
@@ -1405,16 +1256,11 @@
1405
1256
  },
1406
1257
  {
1407
1258
  "tool": "start_campaign",
1408
- "requiredFields": [
1409
- "campaignId"
1410
- ]
1259
+ "requiredFields": ["campaignId"]
1411
1260
  },
1412
1261
  {
1413
1262
  "tool": "update_campaign",
1414
- "requiredFields": [
1415
- "campaignId",
1416
- "currentStep"
1417
- ],
1263
+ "requiredFields": ["campaignId", "currentStep"],
1418
1264
  "requiredValues": {
1419
1265
  "currentStep": "running"
1420
1266
  }
@@ -1432,7 +1278,8 @@
1432
1278
  "get_campaign",
1433
1279
  "start_campaign",
1434
1280
  "update_campaign",
1435
- "AskUserQuestion"
1281
+ "AskUserQuestion",
1282
+ "request_user_input"
1436
1283
  ],
1437
1284
  "watchRequired": true,
1438
1285
  "waitFor": "campaign_started",
@@ -1452,13 +1299,8 @@
1452
1299
  "action": "surface_campaign_live_confirmation"
1453
1300
  }
1454
1301
  ],
1455
- "allowedTools": [
1456
- "get_campaign",
1457
- "AskUserQuestion"
1458
- ],
1459
- "doNotAllow": [
1460
- "start_campaign"
1461
- ],
1302
+ "allowedTools": ["get_campaign", "AskUserQuestion", "request_user_input"],
1303
+ "doNotAllow": ["start_campaign"],
1462
1304
  "terminal": true
1463
1305
  },
1464
1306
  {
@@ -1486,13 +1328,8 @@
1486
1328
  ]
1487
1329
  }
1488
1330
  ],
1489
- "allowedTools": [
1490
- "AskUserQuestion"
1491
- ],
1492
- "doNotAllow": [
1493
- "start_campaign",
1494
- "import_leads"
1495
- ],
1331
+ "allowedTools": ["AskUserQuestion", "request_user_input"],
1332
+ "doNotAllow": ["start_campaign", "import_leads"],
1496
1333
  "terminal": true
1497
1334
  },
1498
1335
  {
@@ -1515,14 +1352,8 @@
1515
1352
  ]
1516
1353
  }
1517
1354
  ],
1518
- "allowedTools": [
1519
- "AskUserQuestion"
1520
- ],
1521
- "doNotAllow": [
1522
- "create_campaign",
1523
- "save_rubrics",
1524
- "import_leads"
1525
- ],
1355
+ "allowedTools": ["AskUserQuestion", "request_user_input"],
1356
+ "doNotAllow": ["create_campaign", "save_rubrics", "import_leads"],
1526
1357
  "terminal": true
1527
1358
  },
1528
1359
  {
@@ -1535,9 +1366,7 @@
1535
1366
  },
1536
1367
  {
1537
1368
  "action": "reset_draft_artifacts",
1538
- "preserve": [
1539
- "brief.md"
1540
- ],
1369
+ "preserve": ["brief.md"],
1541
1370
  "delete": [
1542
1371
  "lead-review.md",
1543
1372
  "lead-sample.json",
@@ -1547,14 +1376,8 @@
1547
1376
  ]
1548
1377
  }
1549
1378
  ],
1550
- "allowedTools": [
1551
- "AskUserQuestion"
1552
- ],
1553
- "doNotAllow": [
1554
- "create_campaign",
1555
- "save_rubrics",
1556
- "import_leads"
1557
- ],
1379
+ "allowedTools": ["AskUserQuestion", "request_user_input"],
1380
+ "doNotAllow": ["create_campaign", "save_rubrics", "import_leads"],
1558
1381
  "terminal": true
1559
1382
  },
1560
1383
  {
@@ -1567,26 +1390,12 @@
1567
1390
  },
1568
1391
  {
1569
1392
  "action": "reset_draft_artifacts",
1570
- "preserve": [
1571
- "brief.md",
1572
- "lead-review.md",
1573
- "lead-sample.json"
1574
- ],
1575
- "delete": [
1576
- "lead-filter.md",
1577
- "message-validation.md",
1578
- "rubric.json"
1579
- ]
1393
+ "preserve": ["brief.md", "lead-review.md", "lead-sample.json"],
1394
+ "delete": ["lead-filter.md", "message-validation.md", "rubric.json"]
1580
1395
  }
1581
1396
  ],
1582
- "allowedTools": [
1583
- "AskUserQuestion"
1584
- ],
1585
- "doNotAllow": [
1586
- "create_campaign",
1587
- "save_rubrics",
1588
- "import_leads"
1589
- ],
1397
+ "allowedTools": ["AskUserQuestion", "request_user_input"],
1398
+ "doNotAllow": ["create_campaign", "save_rubrics", "import_leads"],
1590
1399
  "terminal": true
1591
1400
  },
1592
1401
  {
@@ -1605,19 +1414,11 @@
1605
1414
  "lead-sample.json",
1606
1415
  "lead-filter.md"
1607
1416
  ],
1608
- "delete": [
1609
- "message-validation.md"
1610
- ]
1417
+ "delete": ["message-validation.md"]
1611
1418
  }
1612
1419
  ],
1613
- "allowedTools": [
1614
- "AskUserQuestion"
1615
- ],
1616
- "doNotAllow": [
1617
- "create_campaign",
1618
- "save_rubrics",
1619
- "import_leads"
1620
- ],
1420
+ "allowedTools": ["AskUserQuestion", "request_user_input"],
1421
+ "doNotAllow": ["create_campaign", "save_rubrics", "import_leads"],
1621
1422
  "terminal": true
1622
1423
  },
1623
1424
  {
@@ -1629,14 +1430,8 @@
1629
1430
  "target": ".aborted/"
1630
1431
  }
1631
1432
  ],
1632
- "allowedTools": [
1633
- "AskUserQuestion"
1634
- ],
1635
- "doNotAllow": [
1636
- "create_campaign",
1637
- "save_rubrics",
1638
- "import_leads"
1639
- ],
1433
+ "allowedTools": ["AskUserQuestion", "request_user_input"],
1434
+ "doNotAllow": ["create_campaign", "save_rubrics", "import_leads"],
1640
1435
  "terminal": true
1641
1436
  }
1642
1437
  ]
@@ -98,9 +98,13 @@ exactly:
98
98
  Status: approval-packet
99
99
  ```
100
100
 
101
- The same assistant turn must then call `AskUserQuestion` with the six commit
102
- choices. Do not show a standalone commit-gate question in a later turn without
103
- the approval packet above it.
101
+ The same assistant turn must then use the host-native structured question gate
102
+ with the six commit choices. In Claude Code, call `AskUserQuestion`. In Codex,
103
+ call `request_user_input` when that tool is available. Do not show a standalone
104
+ commit-gate question in a later turn without the approval packet above it. If
105
+ the session is non-interactive or neither structured question tool is exposed,
106
+ fall back to a normal chat question with the exact same choices and say that the
107
+ structured gate is unavailable in this session.
104
108
 
105
109
  The packet should read like an AI GTM engineer explaining the campaign, not an
106
110
  internal validation report. Start with the practical direction in plain
@@ -199,8 +203,8 @@ revise-messaging
199
203
  abort
200
204
  ```
201
205
 
202
- Use `AskUserQuestion` with these 6 options. Do not collapse, reorder, or add
203
- choices. Do not auto-select.
206
+ Use the host-native structured question gate with these 6 options. Do not
207
+ collapse, reorder, or add choices. Do not auto-select.
204
208
 
205
209
  If the host UI limits options per question, preserve all six routes with a
206
210
  two-question gate instead of mentioning implementation limits: