@sellable/mcp 0.1.295 → 0.1.297
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/tools/rows.js
CHANGED
|
@@ -97,7 +97,25 @@ export async function getTableRowsMinimal(tableId, options) {
|
|
|
97
97
|
return api.get(path);
|
|
98
98
|
}
|
|
99
99
|
export function normalizeRowIds(rowIds) {
|
|
100
|
-
|
|
100
|
+
if (Array.isArray(rowIds)) {
|
|
101
|
+
return rowIds.map((rowId) => rowId.trim()).filter(Boolean);
|
|
102
|
+
}
|
|
103
|
+
const trimmed = rowIds.trim();
|
|
104
|
+
if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
|
|
105
|
+
try {
|
|
106
|
+
const parsed = JSON.parse(trimmed);
|
|
107
|
+
if (Array.isArray(parsed)) {
|
|
108
|
+
return parsed
|
|
109
|
+
.filter((rowId) => typeof rowId === "string")
|
|
110
|
+
.map((rowId) => rowId.trim())
|
|
111
|
+
.filter(Boolean);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
// Fall through to comma-splitting for malformed JSON-like input.
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
const rawIds = rowIds.split(",");
|
|
101
119
|
return rawIds.map((rowId) => rowId.trim()).filter(Boolean);
|
|
102
120
|
}
|
|
103
121
|
export async function getRows(tableId, rowIds) {
|
package/package.json
CHANGED
|
@@ -87,6 +87,9 @@ Required:
|
|
|
87
87
|
the brief justifies absence with reference to a specific archived winner.
|
|
88
88
|
If a candidate uses `two options:`, option `a)` and option `b)` must be
|
|
89
89
|
separated by a blank line so the CTA scans cleanly on mobile.
|
|
90
|
+
- **Template spacing enforcement.** The Selected Winner and Approved Message
|
|
91
|
+
Template must use real blank lines between beats/sentences. Reject any body
|
|
92
|
+
with 3+ consecutive non-empty prose lines separated only by single newlines.
|
|
90
93
|
- **All Sellable cleanup rules, including all 8 substance filters from
|
|
91
94
|
`sellable-cleanup-rules.md`, MUST PASS per candidate.** A candidate that fails
|
|
92
95
|
any cleanup rule or substance filter is BLOCKED. The Finalizer Pass CANNOT
|
|
@@ -237,7 +237,7 @@ headlineICPCriteria })` ->
|
|
|
237
237
|
re-run a narrow campaign-scoped `search_signals` call to recover current
|
|
238
238
|
post rows, or ask the user to promote the desired posts in the UI and then
|
|
239
239
|
retry `import_leads`.
|
|
240
|
-
|
|
240
|
+
Start Import approval is the explicit confirmation for this selected-post
|
|
241
241
|
scrape; do not ask for a second yes/no gate between
|
|
242
242
|
`select_promising_posts` and `import_leads`.
|
|
243
243
|
- Sales Nav: `get_provider_prompt({ provider: "sales-nav", campaignOfferId,
|
|
@@ -387,6 +387,26 @@ templateRevision: "current" })` until the first current-revision generated
|
|
|
387
387
|
6. On success, keep `currentStep: "auto-execute-messaging"` and ask the user to
|
|
388
388
|
approve the generated message before continuing to Settings. Only that
|
|
389
389
|
approval may move the campaign to Settings / `awaiting-user-greenlight`.
|
|
390
|
+
7. When approval is given — or auto-approved in YOLO when the Recommendation is
|
|
391
|
+
`approve-message` — you MUST actually mark the reviewed passing rows approved
|
|
392
|
+
by calling `update_cell({ cellId: <approveCellId>, value: true })` for at
|
|
393
|
+
least one generated-message row, preferably two when available (read each
|
|
394
|
+
`approveCellId` from `get_rows`). The campaign UI gates "Next: Settings" on
|
|
395
|
+
at least one row whose `Approved` cell is true:
|
|
396
|
+
moving `currentStep` to `settings`/`awaiting-user-greenlight` with zero
|
|
397
|
+
approved rows desyncs the watch UI, which stays stuck on Generate Messages
|
|
398
|
+
showing "Approve at least one draft to continue." Setting the `Approved`
|
|
399
|
+
flag via `update_cell({ cellId: approveCellId, value: true })` is explicitly
|
|
400
|
+
allowed; the "do not use `update_cell`" rule below applies ONLY to message
|
|
401
|
+
bodies, never to the `Approved` flag. Advance `currentStep` only after the
|
|
402
|
+
approve writes succeed.
|
|
403
|
+
If any Settings/sequence/send/start step call returns
|
|
404
|
+
`error: "approved_message_required"` with
|
|
405
|
+
`requiredAction: "approve_generated_message"`, recover by reading rows with
|
|
406
|
+
`get_rows`, writing `update_cell({ cellId: approveCellId, value: true })`
|
|
407
|
+
for a completed generated-message row, confirming the approved count is at
|
|
408
|
+
least 1, then retrying the blocked action. Do not ignore or route around
|
|
409
|
+
that error with a different currentStep write.
|
|
390
410
|
|
|
391
411
|
**Do NOT hand-write message bodies via `update_cell`.** `update_cell`
|
|
392
412
|
is reachable for legitimate operator overrides AFTER the tail hands
|
|
@@ -435,9 +455,15 @@ strings, which is why Step 16 requires Step 15 to be complete.
|
|
|
435
455
|
`maxRevisionRounds` cap.
|
|
436
456
|
7. On success, keep `currentStep: "auto-execute-messaging"`, show that the
|
|
437
457
|
first passing generated message is ready in Messages, and ask for approval
|
|
438
|
-
before Settings.
|
|
439
|
-
`
|
|
440
|
-
|
|
458
|
+
before Settings. When the user approves (or YOLO auto-approves on an
|
|
459
|
+
`approve-message` recommendation), first write the approval to the rows with
|
|
460
|
+
`update_cell({ cellId: <approveCellId>, value: true })` for at least one
|
|
461
|
+
reviewed passing row, preferably two when available, confirm the table now
|
|
462
|
+
reports `approved >= 1`, and only then run
|
|
463
|
+
`update_campaign({ campaignId, currentStep: "awaiting-user-greenlight" })`.
|
|
464
|
+
Never advance to Settings while the table still reports `approved: 0` — the
|
|
465
|
+
builder UI will refuse to leave Generate Messages and the watch step will
|
|
466
|
+
desync from the headless step.
|
|
441
467
|
|
|
442
468
|
Critique failure modes NEVER escalate. A critic timeout, a total
|
|
443
469
|
timeout, a budget trip, a fake-proof rejection, or an unsupported-
|
|
@@ -470,7 +496,7 @@ Shape:
|
|
|
470
496
|
sender to attach. Attach only after the user chooses. In explicit UAT safe
|
|
471
497
|
mode, use only the safe mock sender; never pick a real sender.
|
|
472
498
|
7. Call `update_campaign({ campaignId, senderIds: [selectedSenderId],
|
|
473
|
-
currentStep: "sequence" })` to attach the sender through the v3 senders
|
|
499
|
+
currentStep: "sequence" })` to attach the sender through the v3 senders
|
|
474
500
|
route and describe the Sequence view.
|
|
475
501
|
8. Call `attach_recommended_sequence({ campaignId, currentStep: "send" })`
|
|
476
502
|
(bind the tier-recommended sequence to the campaign). Explain the sequence
|
|
@@ -482,12 +508,12 @@ currentStep: "sequence" })` to attach the sender through the v3 senders
|
|
|
482
508
|
`update_campaign({ campaignId, currentStep: "send" })`.
|
|
483
509
|
9. Surface the `handoff.orientation` string from `auto-execute.yaml` without
|
|
484
510
|
repeating the watch URL.
|
|
485
|
-
|
|
511
|
+
10. Ask the final launch greenlight with the structured question function:
|
|
486
512
|
Start campaign, Review campaign first, or Pause here.
|
|
487
|
-
|
|
513
|
+
11. STOP unless the user explicitly chooses Start campaign. Do NOT call
|
|
488
514
|
`start_campaign` from Step 16 itself; that belongs only to the Claude
|
|
489
515
|
greenlight path. The autonomous tail ends here.
|
|
490
|
-
|
|
516
|
+
12. Make the credit boundary explicit in the handoff: only the first review
|
|
491
517
|
batch has been enriched/messaged; expanding to more leads requires a
|
|
492
518
|
separate user instruction.
|
|
493
519
|
|
|
@@ -558,7 +584,7 @@ runs.
|
|
|
558
584
|
| `references/final-handoff-contract.md` | Step 16, and every Claude greenlight turn |
|
|
559
585
|
| `references/parallel-critique-protocol.md` | Step 15 when `messaging.critique.enabled` is true |
|
|
560
586
|
| `references/thomas-variant-selection.md` | Step 15 when `messaging.critique.opus.enabled` is true |
|
|
561
|
-
| `references/sellable-cleanup-rules.md`
|
|
587
|
+
| `references/sellable-cleanup-rules.md` | Any critique rewrite, before persisting |
|
|
562
588
|
| `core/auto-execute.yaml` | Start of Step 13, load once; all tail steps read parsed values |
|
|
563
589
|
| `core/auto-execute.README.md` | When tuning `auto-execute.yaml` knobs or reviewing threshold-trip logs |
|
|
564
590
|
|
|
@@ -252,6 +252,11 @@ Orchestration requirements:
|
|
|
252
252
|
product/problem -> next step. If two adjacent lines could be swapped, deleted,
|
|
253
253
|
or connected with `anyway` without changing the meaning, the transition is
|
|
254
254
|
fake and the draft must be revised.
|
|
255
|
+
- pass the template-spacing gate before writing findings. The Selected Winner
|
|
256
|
+
and any Approved Message Template must use actual blank lines between message
|
|
257
|
+
beats/sentences. If there are 3+ consecutive non-empty prose lines separated
|
|
258
|
+
only by single newlines, the draft is blocked until rewritten with double
|
|
259
|
+
newlines.
|
|
255
260
|
- pass the final-line/PS "so what?" gate before writing findings. The final
|
|
256
261
|
line must lower commitment, preview a specific next step, answer a
|
|
257
262
|
trust/category objection, tie proof to buyer value, or be omitted.
|
|
@@ -2118,6 +2118,15 @@ signoff is a talk-at shape).
|
|
|
2118
2118
|
|
|
2119
2119
|
- **each sentence is its own paragraph** — put a blank line between every sentence in the body, even short ones
|
|
2120
2120
|
- literally: the body should render as a sequence of one-line paragraphs separated by blank lines, not as multi-sentence paragraphs
|
|
2121
|
+
- the approved template must contain the literal blank lines. Do not fake
|
|
2122
|
+
paragraph spacing by putting each sentence on adjacent single-newline lines.
|
|
2123
|
+
If the template or Selected Winner has 3+ consecutive non-empty prose lines
|
|
2124
|
+
with no blank line between them, mark it `revise-message` / `blocked` and
|
|
2125
|
+
rewrite before approval.
|
|
2126
|
+
- bad shape:
|
|
2127
|
+
`saw you in a few conversations about corporate comms, so may be off, but this seemed relevant.\nyour team probably puts a lot of work into getting people on webinars.\nArbor turns those recordings into ready-to-publish content.`
|
|
2128
|
+
- good shape:
|
|
2129
|
+
`saw you in a few conversations about corporate comms, so may be off, but this seemed relevant.\n\nyour team probably puts a lot of work into getting people on webinars.\n\nArbor turns those recordings into ready-to-publish content.`
|
|
2121
2130
|
- this matches the archived winners (Revvix, Galley, Superposition all paragraph-break per sentence). It gives the reader one idea at a time and lets short sentences breathe
|
|
2122
2131
|
- mobile scanability is a hard requirement. The winner should read cleanly in a one-thumb scroll on a phone
|
|
2123
2132
|
- keep most sentences in the **6-14 word** range. If a sentence is above ~18 words or has more than one comma, split it
|
|
@@ -2913,6 +2922,7 @@ research → condense → 10 angle agents in parallel → finalizer combines bes
|
|
|
2913
2922
|
- Flow skeleton: opener → pain → **what the product IS** → **what it DOES** (one action per line, up to three; prefer short bullets for 3 repeated-subject product actions) → deployment ease → CTA → optional PS
|
|
2914
2923
|
- A cold reader must be able to state what the product does in one sentence after reading. Require a crisp `Product is an X that does Y` anchor before any action breakdown. Do not gesture at "that chain" / "the stack" / "that work"
|
|
2915
2924
|
- Blank line between every sentence in the body. The body renders as a sequence of one-line paragraphs separated by blank lines, not as multi-sentence paragraphs. Target 6-10 one-line paragraphs
|
|
2925
|
+
- The approved template must include actual double-newline paragraph breaks. Never approve or return a body with 3+ consecutive non-empty prose lines separated only by single newlines.
|
|
2916
2926
|
- 5th-grade reading level by default. Cut glue language (handoff, order-to-cash, rip-and-replace). Keep brief-native product/tool names (Shopify, HubSpot)
|
|
2917
2927
|
- No feature/benefit marketing bullet lists, no "I noticed...", no compliment sandwiches, no em dashes unless the canonical example uses one. Exception: use a short bullet stack when 3 adjacent product actions repeat the same subject pattern and bullets improve mobile readability.
|
|
2918
2928
|
- No synthesized framing ("at your stage", "in a setup like yours", "running X means...", "X means you're likely...")
|