@sellable/mcp 0.1.345 → 0.1.347

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sellable/mcp",
3
- "version": "0.1.345",
3
+ "version": "0.1.347",
4
4
  "type": "module",
5
5
  "description": "Sellable MCP server for Claude Code and Codex campaign workflows",
6
6
  "main": "dist/index.js",
@@ -63,6 +63,15 @@ currentStep: "sequence" })` to attach the sender via the v3 senders route and
63
63
  and Paid InMail Campaign is only an explicit paid-InMail opt-in because it
64
64
  can spend InMail credits. If that response does not persist `currentStep:
65
65
  "send"`, call `update_campaign({ campaignId, currentStep: "send" })`.
66
+ Then reread `get_campaign({ campaignId })` and `list_tables()` and verify the
67
+ current `workflowTableId` has `hasSequence:true`. A campaign-level
68
+ `SEQUENCE_EXISTS` response is not enough when `confirm_lead_list` or another
69
+ copy step has moved the campaign to a new current campaign table while an old
70
+ stale shell table still owns the sequence columns. In that stale-shell case,
71
+ either repair only the current workflowTableId with `attach_sequence` using
72
+ the same non-paid product template the recommended selector would have chosen,
73
+ or stop and report the stale-shell sequence blocker if replacement was not
74
+ explicitly approved. Never choose a paid-InMail template for this repair.
66
75
  9. Surface the `handoff.orientation` string from `auto-execute.yaml` and
67
76
  summarize the visible Settings/Sequence/Send state without repeating the
68
77
  watch URL.
@@ -141,7 +150,11 @@ order, atomically:
141
150
  2. **Validate sender + sequence state.** If no sender is attached, refuse start
142
151
  and return the Settings link. If no sequence is attached but a sender is
143
152
  attached, call `attach_recommended_sequence({ campaignId, currentStep:
144
- "send" })` before approving messages.
153
+ "send" })` before approving messages, then rerun the precondition check against
154
+ the current workflowTableId rather than an older shell table. If
155
+ `SEQUENCE_EXISTS` only proves an old shell while the current table lacks
156
+ `hasSequence:true`, stop or perform the explicitly approved stale-shell
157
+ current-table repair before any launch.
145
158
  3. **Approve generated messages** through the bounded or broad path:
146
159
  - If the user asked for an exact send count, such as "schedule 250 sends",
147
160
  verify the preparation job approved only the bounded prepared cohort for
@@ -68,6 +68,7 @@ Step 16 — awaiting-user-greenlight
68
68
  ask the user which connected sender to attach; in explicit UAT safe mode only, use the safe mock sender
69
69
  update_campaign(senderIds=[selectedSenderId], currentStep=sequence)
70
70
  attach_recommended_sequence({ campaignId, currentStep: "send" }) # tier-aware: premium/SN -> If Open Profile->INMAIL_OPEN, else INVITE->accepted->DM
71
+ reread get_campaign + list_tables; verify hasSequence:true on the current workflowTableId, not an older shell table
71
72
  if the attach response did not move the UI: update_campaign(currentStep=send)
72
73
  surface campaign setup orientation + final launch choices without repeating the watch URL
73
74
  STOP. DO NOT call start_campaign. DO NOT move to running without explicit launch greenlight.
@@ -81,7 +82,13 @@ hand-author a `version: 2` template with nodes, branches, and
81
82
  entryNodeId — that's error-prone mid-long-context (galley-off UAT
82
83
  `20260420T195732Z` failed because Claude hit "Invalid node type" and
83
84
  tried to debug via forbidden Bash/Glob calls). Use `attach_sequence`
84
- only when the caller explicitly needs a custom non-recommended cadence.
85
+ only when the caller explicitly needs a custom non-recommended cadence, or when
86
+ you have just reread the campaign after `confirm_lead_list` and proved the
87
+ current campaign table has no sequence while an older stale shell table is
88
+ causing campaign-level `SEQUENCE_EXISTS`. In that stale-shell repair case, use
89
+ `attach_sequence` on the current workflowTableId with the same non-paid product
90
+ template the backend would select; never choose a paid-InMail template and never
91
+ repair a table other than the current workflowTableId.
85
92
 
86
93
  Hard gates — if you find yourself about to violate any of these, stop
87
94
  first:
@@ -532,6 +539,14 @@ Shape:
532
539
  opt-in because it can spend InMail credits. If the tool response
533
540
  does not persist `currentStep: "send"`, call
534
541
  `update_campaign({ campaignId, currentStep: "send" })`.
542
+ Then reread `get_campaign({ campaignId })` and `list_tables()` and verify the
543
+ returned current workflowTableId has `hasSequence:true`. If
544
+ `attach_recommended_sequence` returned `SEQUENCE_EXISTS` but the current table
545
+ still has `hasSequence:false`, do not continue to launch handoff from that
546
+ stale shell proof. Repair only the current workflowTableId with
547
+ `attach_sequence` using the same non-paid product template the recommended
548
+ selector would have chosen, or stop and report the stale-shell sequence
549
+ blocker if replacement was not explicitly approved.
535
550
  9. Surface the `handoff.orientation` string from `auto-execute.yaml` without
536
551
  repeating the watch URL.
537
552
  10. Ask the final launch greenlight with the structured question function:
@@ -129,7 +129,22 @@ filter choice, Message Drafting, packaged `generate-messages`, sequence
129
129
  attachment, and send-review readiness. Do not rebuild those steps ad hoc in the
130
130
  parent thread.
131
131
 
132
- Workers return worker receipts. The parent then calls
132
+ Workers return worker receipts. Each customer-visible lane receipt must include
133
+ message proof from `watchNarration.workerDetails.messageDraftBuilder` or the
134
+ worker's equivalent handoff record. Valid message proof names the current
135
+ campaign id, workflowTableId, selected lead-list or source id, filter choice,
136
+ review-batch row ids/hash, and either `statusSource:"branch"` or
137
+ `statusSource:"parent-thread-fallback"`. It must prove the worker loaded the
138
+ full packaged prompt with `get_subskill_prompt({ subskillName:"generate-messages"`
139
+ until `hasMore:false`, loaded the required message assets, and loaded
140
+ `create-campaign-v2-validation` before returning a `messageDraftRecommendation`.
141
+ The generated-message cells are not prompt proof: `currentRevisionGeneratedMessages`,
142
+ Generate Message column counts, `messagesCount`, or rendered row previews prove
143
+ only that table cells exist from the current brief/template, not that the
144
+ create-campaign Message Drafting branch ran. If this receipt is missing, report
145
+ `blocked: missing_message_drafting_receipt` and do not call the lane complete.
146
+
147
+ The parent then calls
133
148
  `setup_evergreen_campaigns({ mode:"verify", planRevision, selectedActionIds,
134
149
  receipts })` and report only verified completion. If verify blocks, report the
135
150
  blocker and repair only the missing postconditions from the same current plan.
@@ -179,26 +194,62 @@ Parent-thread handwritten copy or setting `currentStep` is not proof.
179
194
  - Message Drafting has run from the current campaign/table basis, using the
180
195
  create-campaign message prompt/assets and validation gate. Updating
181
196
  `currentStep:"messages"` is not proof. Parent-thread handwritten copy is
182
- not a substitute.
197
+ not a substitute. The proof receipt must show
198
+ `get_subskill_prompt({ subskillName:"generate-messages"` was loaded until
199
+ `hasMore:false`, required message assets were loaded, and
200
+ `create-campaign-v2-validation` ran through either
201
+ `workerDetails.messageDraftBuilder` with `statusSource:"branch"` or an
202
+ inline `statusSource:"parent-thread-fallback"` receipt. The generated-message
203
+ cells are not prompt proof; `currentRevisionGeneratedMessages` and row
204
+ previews are only downstream cell evidence.
183
205
  - The first review batch exists and at least 3 review rows have generated
184
206
  messages from the approved brief. If fewer than 3 usable rows exist, report
185
207
  the actual count and why.
208
+ If a bounded preparation job requested more than the minimum but already
209
+ met the minimum generated-message floor, do not stall on a single bad review row once a fresh status/readiness check shows no queued, processing, or active cells; record the shortfall, name the failed/empty-row reason when
210
+ available, and continue with route-proof review rather than expanding source
211
+ or waiting forever.
186
212
  - At least one generated row is approved as a route-proof gate. If zero rows
187
213
  are approved and the prompt explicitly asked for full/customer-ready
188
214
  completion, approve exactly one quality-valid generated row. If one or more
189
215
  rows are already approved, do not add more approvals during evergreen
190
216
  completion. Never broad approve all rows.
191
- - The recommended non-paid sequence is attached, and the watched campaign is
192
- on Send. Use `attach_recommended_sequence({ campaignId, currentStep:"send" })`
193
- when a safe attach is needed. Existing sequence proof may come from
194
- `SEQUENCE_EXISTS`; do not replace it without explicit user confirmation.
217
+ - The recommended non-paid sequence is attached to the current campaign
218
+ table, and the watched campaign is on Send. Use
219
+ `attach_recommended_sequence({ campaignId, currentStep:"send" })` when a
220
+ safe attach is needed. After `confirm_lead_list` or any source-list copy,
221
+ immediately reread `get_campaign({ campaignId })`; the returned
222
+ `workflowTableId` is the current campaign table. Cross-check that exact
223
+ current workflowTableId with `list_tables` and require `hasSequence:true`
224
+ before reporting completion. If a stale shell table has sequence columns but
225
+ the current campaign table does not, `SEQUENCE_EXISTS` is not enough:
226
+ record the stale shell table id, then repair the current workflowTableId
227
+ with `attach_sequence` using the same non-paid product template
228
+ `attach_recommended_sequence` would have selected. Never use a paid-InMail
229
+ template and never attach/replace sequence outside the current table unless
230
+ the current lane packet explicitly allowed sequence repair.
195
231
  - No scheduled, queued outbound, sent outbound, campaign launch, or paid
196
232
  InMail spend is created by this skill.
197
233
  4. **Verify each slot** after create/reuse/repair:
198
234
  - `get_campaign` shows the campaign exists, remains unlaunched, and has the expected workflow table.
199
235
  - Builder truth must match dashboard truth. `currentStep:"running"` is valid only when the linked table has `campaignStatus:"ACTIVE"`. For a `PAUSED` or `ARCHIVED` campaign/table, repair or flag stale `currentStep:"running"` back to launch review (`send` / review-ready) before reporting the slot done. Never call `start_campaign` just to make a stale `running` step true.
200
- - Send/action lanes such as Post Engagers have a sequence attached. Use `list_tables({ hasSequence: true })` as a quick cross-check, but do not treat that filter as the only proof. If the canonical campaign/table is missing from the sequence-filtered table list but a safe `attach_recommended_sequence({ campaignId })` repair/precheck returns `SEQUENCE_EXISTS`, record `sequence attached (verified by SEQUENCE_EXISTS precheck; list_tables.hasSequence mismatch)` and do not retry.
201
- - Only use `attach_recommended_sequence({ campaignId })` for a send-lane sequence repair/precheck when the target is a canonical prod slot and the invoking prompt allows sequence repair. Call it at most once without `confirmed`; a successful response is `repaired`, and `SEQUENCE_EXISTS` is non-mutating proof that a sequence already exists. Never call `attach_recommended_sequence` or `attach_sequence` with `confirmed:true` in evergreen automation unless the user explicitly asks to replace an existing sequence.
236
+ - Send/action lanes such as Post Engagers have a sequence attached on the
237
+ exact current campaign table. Use `list_tables({ hasSequence: true })` as a
238
+ quick cross-check, but do not treat that filter as the only proof. If the
239
+ canonical current campaign table is missing from the sequence-filtered
240
+ table list and `attach_recommended_sequence({ campaignId })` returns
241
+ `SEQUENCE_EXISTS`, inspect whether a stale shell table owns the sequence.
242
+ For a customer-visible completion run, stale shell proof is not completion:
243
+ rerun the current-table repair above or report `blocked: stale_shell_sequence`.
244
+ - Only use `attach_recommended_sequence({ campaignId })` for a send-lane
245
+ sequence repair/precheck when the target is a canonical prod slot and the
246
+ invoking prompt allows sequence repair. Call it at most once without
247
+ `confirmed`; a successful response is `repaired`. Treat `SEQUENCE_EXISTS` as
248
+ non-mutating proof only when the current table also has `hasSequence:true`.
249
+ Never call `attach_recommended_sequence` or `attach_sequence` with
250
+ `confirmed:true` in evergreen automation unless the user explicitly asks to
251
+ replace an existing sequence or the approved lane packet allows current
252
+ table stale-shell repair.
202
253
  - Do not report `source-only/no sequence expected` for any named evergreen
203
254
  campaign that appears in Campaigns, has a CampaignOffer ID, or is backed by
204
255
  a campaign dashboard table. Shared Signal Discovery and Shared Cold