@sellable/mcp 0.1.5 → 0.1.7

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,52 +80,60 @@ 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.7 --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.7 --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
101
+ - installs the `sellable@sellable` Desktop plugin so Codex Desktop loads the
102
+ `mcp__sellable__*` tools into skill sessions
108
103
 
109
- If you already have `~/.sellable/config.json`, verify the install without
110
- rewriting auth:
104
+ After the installer passes, fully quit and reopen Codex Desktop. Start a new
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"]`.
110
+ The skill being visible only proves skill discovery; the plugin is what mounts
111
+ the Sellable MCP tools for Codex Desktop.
111
112
 
112
- ```bash
113
- npm run sellable:codex:install -- --verify-only
114
- ```
113
+ ## Public Names And Host Commands
115
114
 
116
- For published-package installs instead of this local checkout:
115
+ Use these names consistently:
117
116
 
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
- ```
117
+ - Claude Code command: `/sellable:create-campaign`
118
+ - Codex command: `$sellable:create-campaign`
119
+ - Codex Desktop plugin: `sellable@sellable`
120
+ - Codex visible skill: `Sellable Create Campaign`
121
+ - Codex skill frontmatter name: `create-campaign`
122
+ - MCP server name: `sellable`
123
+ - Internal workflow prompt: `create-campaign-v2`
121
124
 
122
- 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"]`.
127
- The skill being visible only proves skill discovery; the plugin is what mounts
128
- the Sellable MCP tools for Codex Desktop.
125
+ Never tell users to run `/sellable:create-campaign-v2`,
126
+ `$sellable:create-campaign-v2`, or `$sellable:sellable:create-campaign`.
127
+ `create-campaign-v2` is an internal MCP subskill loaded by
128
+ `get_subskill_prompt({ subskillName: "create-campaign-v2" })`.
129
+
130
+ ## Structured Question Parity
131
+
132
+ Claude Code should ask intake and approval gates with `AskUserQuestion`.
133
+ Codex should ask them with `request_user_input` when it is exposed in an
134
+ interactive Plan/collaboration-mode session. `codex exec` is non-interactive
135
+ and cannot show the structured questionnaire UI, so it is only useful for smoke
136
+ checks that stop before human intake/approval.
129
137
 
130
138
  ## Usage
131
139
 
@@ -164,9 +172,9 @@ Use the Codex skill entrypoint:
164
172
  $sellable:create-campaign
165
173
  ```
166
174
 
167
- Skill package path in this repo:
175
+ Installed skill package path:
168
176
 
169
- - `.agents/skills/sellable-create-campaign/SKILL.md`
177
+ - `~/.codex/plugins/cache/sellable/sellable/<version>/skills/sellable-create-campaign/SKILL.md`
170
178
 
171
179
  ## Host Parity Runbook (Codex + Claude)
172
180
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sellable/mcp",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
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,31 @@ 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` (usually exposed in Plan/collaboration-mode interactive
80
+ sessions, not `codex exec`). Treat them as equivalent approval/intake gates and
81
+ persist the same draft artifacts after the user answers. If an interactive
82
+ Codex session does not expose `request_user_input`, do not silently degrade to
83
+ a plain chat question; stop and tell the user: `Codex has not exposed
84
+ request_user_input in this session. Switch to Plan mode / collaboration mode
85
+ for the structured questionnaire, then rerun $sellable:create-campaign.` In
86
+ non-interactive `codex exec`, structured user input is unavailable by design;
87
+ ask in chat only when the run is explicitly a non-interactive smoke/rehearsal.
77
88
  - Fast Intake Mode is mandatory for hosted/rehearsal net-new runs. Ask the
78
89
  first founder strategy/source question packet in under 60 seconds. Before
79
90
  that first packet, the first assistant turn may only call
80
91
  `bootstrap_create_campaign`, load this workflow prompt with
81
92
  `get_subskill_prompt({ subskillName: "create-campaign-v2" })`, optionally run
82
- one lightweight identity lookup, then call `AskUserQuestion`. If the user
93
+ one lightweight identity lookup, then use the structured question gate. If the user
83
94
  supplied a company website/domain, call exactly one of `fetch_company`,
84
95
  `WebFetch`, or `WebSearch` to identify what the company actually does before
85
96
  generating intake options. If the user supplied a LinkedIn profile URL, call
86
97
  `fetch_linkedin_profile` before generating intake options. Do not infer the
87
98
  product category from the company name alone. If no domain, website, or
88
99
  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,
100
+ guessed vertical-specific options. Before the first structured question gate,
101
+ do not run sender research, `list_senders`, source discovery, Sales Nav, Prospeo,
91
102
  Signals, Bash, Read, Write, Edit, Glob, Grep, full company research, or
92
103
  draft-directory inspection/creation. Do draft-directory setup only after the
93
104
  founder answers. The first intake packet must ask buyer, offer/CTA, proof, and
@@ -199,9 +210,9 @@ There are two human gates:
199
210
  Earlier artifact gates are interrupt-only unless this contract explicitly
200
211
  names the `message-review` gate.
201
212
 
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.
213
+ Auto-continue without a structured question gate when the artifact says
214
+ `Status: confirmed` (or equivalent), confidence is high/medium, volume is
215
+ viable, and there is no strategic tradeoff.
205
216
 
206
217
  Ask the user only when one of these is true:
207
218
 
@@ -688,9 +699,9 @@ or tone feedback you want before I build the approval packet.` Do not write
688
699
  The next Codex UAT goal is to prove message quality before mint, so no
689
700
  approval packet or campaign mutation should happen just because the mechanics
690
701
  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`,
702
+ - immediately after rendering `message-review.md`, use the structured question
703
+ gate with exactly two choices, in this order: `approve-message`,
704
+ `revise-messaging`. Stop after the question. Do not write `approval-packet.md`,
694
705
  `customer-roleplay.md`, or a commit-gate question until
695
706
  `message-review-decision.md` contains `approve-message`.
696
707
  - if the selected winner or PS uses named customer/logo proof, quantified proof,
@@ -821,7 +832,7 @@ Do not:
821
832
  invitation to give manual feedback before approval
822
833
  - `Question: approve-message or revise-messaging?`
823
834
  - `Recommendation:` exactly `approve-message` or `revise-messaging`
824
- - The two-choice `AskUserQuestion` immediately after the rendered review
835
+ - The two-choice structured question gate immediately after the rendered review
825
836
 
826
837
  `message-review-decision.md` must contain exactly one selected route:
827
838
  `approve-message` or `revise-messaging`. It does not authorize DB mutation.
@@ -956,15 +967,17 @@ anchors at the user.
956
967
 
957
968
  When rendering the approval packet inline, start it with exactly
958
969
  `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
970
+ before showing the gate. The same assistant turn must then use the structured
971
+ question gate with the six commit choices below. In Claude Code, call
972
+ `AskUserQuestion`; in Codex, call `request_user_input` when available. A
973
+ commit-gate question without the inline `Status: approval-packet` packet is
974
+ invalid UX. If a
962
975
  customer roleplay is performed, write `customer-roleplay.md` before the final
963
976
  choice. A roleplay result that says "looks good", "approve", or equivalent is
964
977
  only critique; it does not satisfy the gate. Write `commit-gate-decision.md`
965
978
  only after the user/operator makes one explicit choice.
966
979
 
967
- Use `AskUserQuestion` with exactly these 6 choices, in this order:
980
+ Use the structured question gate with exactly these 6 choices, in this order:
968
981
 
969
982
  ```text
970
983
  approve
@@ -1329,6 +1342,33 @@ atomic mint).
1329
1342
  > `search_prospeo`, `search_sales_nav`, `search_apollo`,
1330
1343
  > `search_signals`, and any other provider search tool added later.
1331
1344
  > Campaignless searches after mint orphan results from the campaign UI.
1345
+ >
1346
+ > **Lead-list vs campaign-table identity rule (do not confuse them):**
1347
+ > after the first `confirm_lead_list`, two workflow tables exist:
1348
+ >
1349
+ > - the **lead-list** table (the original `sourceLeadListId` returned by
1350
+ > `import_leads`), and
1351
+ > - the **campaign workflow table** (`CampaignOffer.workflowTableId`,
1352
+ > also returned as `campaignTableId` from `confirm_lead_list`).
1353
+ >
1354
+ > `confirm_lead_list` overwrites `CampaignOffer.selectedLeadListId` with
1355
+ > the campaign-table id. That means after the first confirm, the
1356
+ > campaign-table id is NOT a valid `sourceLeadListId` for any future
1357
+ > `import_leads` call.
1358
+ >
1359
+ > When you scale up the import, `mode: "add"` requires the ORIGINAL
1360
+ > lead-list id (the one returned by the first `import_leads`), never the
1361
+ > campaign-table id. Passing the campaign-table id silently writes
1362
+ > straight into the campaign workflow table, bypassing the lead list
1363
+ > entirely; the lead list stays at its original size and the
1364
+ > campaign-builder `/leads` UI throws "Lead list not found" because it
1365
+ > expects `selectedLeadListId` to resolve as a lead list.
1366
+ >
1367
+ > Capture the original `leadListId` from the FIRST `import_leads`
1368
+ > response and reuse it for every scale-up `import_leads(mode: "add")`
1369
+ > call on the same campaign. If the original id is unknown, query
1370
+ > for the lead-list table by name or skip the `mode: "add"` path; do
1371
+ > not pass the campaign-table id as `sourceLeadListId`.
1332
1372
 
1333
1373
  1. Load `core/auto-execute.yaml`. Capture `import.importLimit`,
1334
1374
  `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,16 @@ 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 an
105
+ interactive Codex session does not expose `request_user_input`, do not silently
106
+ fall back to chat. Stop and tell the user to switch to Plan mode /
107
+ collaboration mode so Codex exposes the structured questionnaire tool, then
108
+ rerun `$sellable:create-campaign`. A normal chat question is acceptable only for
109
+ non-interactive `codex exec` smoke/rehearsal runs because structured user input
110
+ is unavailable by design there.
104
111
 
105
112
  The packet should read like an AI GTM engineer explaining the campaign, not an
106
113
  internal validation report. Start with the practical direction in plain
@@ -199,8 +206,8 @@ revise-messaging
199
206
  abort
200
207
  ```
201
208
 
202
- Use `AskUserQuestion` with these 6 options. Do not collapse, reorder, or add
203
- choices. Do not auto-select.
209
+ Use the host-native structured question gate with these 6 options. Do not
210
+ collapse, reorder, or add choices. Do not auto-select.
204
211
 
205
212
  If the host UI limits options per question, preserve all six routes with a
206
213
  two-question gate instead of mentioning implementation limits: