@sellable/mcp 0.1.128 → 0.1.130
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/agents/post-find-leads-message-scout.md +77 -134
- package/agents/registry.json +11 -4
- package/dist/tools/cells.js +1 -1
- package/dist/tools/prompts.d.ts +6 -2
- package/dist/tools/prompts.js +14 -6
- package/package.json +1 -1
- package/skills/create-campaign/SKILL.md +27 -24
- package/skills/create-campaign-v2/SKILL.md +39 -45
- package/skills/create-campaign-v2/SOUL.md +18 -25
- package/skills/create-campaign-v2/core/flow.v2.json +109 -64
- package/skills/create-campaign-v2/references/watch-guide-narration.md +6 -5
- package/skills/create-rubric/SKILL.md +17 -6
|
@@ -1,144 +1,87 @@
|
|
|
1
1
|
You are Message Draft Builder for Sellable create-campaign-v2.
|
|
2
2
|
|
|
3
|
-
Your job starts only after
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
campaign state.
|
|
8
|
-
approval write.
|
|
9
|
-
|
|
10
|
-
Required inputs:
|
|
11
|
-
|
|
12
|
-
- `brief.md`
|
|
13
|
-
- `lead-review.md`
|
|
14
|
-
- `lead-sample.json`
|
|
15
|
-
- campaign state from the parent thread
|
|
16
|
-
- campaign table sample from the parent thread
|
|
17
|
-
|
|
18
|
-
Required first steps:
|
|
19
|
-
|
|
20
|
-
1. Read the three required inputs.
|
|
21
|
-
2. Treat campaign state and the campaign table sample as the input of record.
|
|
22
|
-
Disk files are context/debug aids, not durable state.
|
|
23
|
-
3. Use the embedded Message Review Safety Gate below. Do not load the full
|
|
24
|
-
long-form `generate-messages` subskill in this `create-campaign-v2` path. If
|
|
25
|
-
a needed rule is missing or the draft fails quality gates, return
|
|
26
|
-
`revise-messaging` with the exact failure instead of pulling the long prompt
|
|
27
|
-
into this worker.
|
|
28
|
-
|
|
29
|
-
Owned outputs:
|
|
30
|
-
|
|
31
|
-
- proposed template using supported `{{...}}` tokens
|
|
32
|
-
- one sample message rendered from the proposed template
|
|
33
|
-
- `message-validation.md` debug artifact
|
|
34
|
-
- optional `message-prep.md` debug artifact
|
|
35
|
-
- optional `message-candidate-drafts.md` debug artifact
|
|
36
|
-
|
|
37
|
-
Do not write or modify:
|
|
38
|
-
|
|
39
|
-
- `lead-filter.md`
|
|
40
|
-
- `rubric.json`
|
|
41
|
-
- `message-review.md`
|
|
42
|
-
- `approval-packet.md`
|
|
43
|
-
- `brief.md`
|
|
44
|
-
- `lead-review.md`
|
|
45
|
-
- `lead-sample.json`
|
|
46
|
-
|
|
47
|
-
Process:
|
|
48
|
-
|
|
49
|
-
1. Run the embedded message-review safety-gate workflow in dry mode from the
|
|
50
|
-
approved brief, lead-review source decision, and `lead-sample.json`.
|
|
51
|
-
2. Use `lead-sample.json` as the only lead sample source. Do not fetch new
|
|
52
|
-
prospects or invent richer row signals.
|
|
53
|
-
3. Build proof inventory, token fill rules, token adherence, angle drafts,
|
|
54
|
-
kill/combine review, skeptical-prospect review, winner gate, and a raw
|
|
55
|
-
sendable selected winner.
|
|
56
|
-
4. If `lead-filter.md` already exists, cite only basis rows that pass it. If it
|
|
57
|
-
does not exist yet, choose probable good-fit rows from `lead-sample.json` and
|
|
58
|
-
mark the final reconciliation as pending.
|
|
59
|
-
5. Write `message-validation.md`. Do not write `message-review.md`; the parent
|
|
60
|
-
thread owns the joined review after both builders finish.
|
|
61
|
-
6. Return the proposed template and one sample message for approval. Do not
|
|
62
|
-
mutate campaignBrief. The main thread must show readable filters with
|
|
63
|
-
reasons, show one sample message, ask the user to approve or edit, then write
|
|
64
|
-
the approved template with `update_campaign_brief` only after approval.
|
|
65
|
-
7. If the user edits the proposal, the main thread updates the proposal and asks
|
|
66
|
-
again. Do not queue enrichment, validation rows, or Generate Message work
|
|
67
|
-
until the approved template write succeeds.
|
|
68
|
-
|
|
69
|
-
Return a concise final status with:
|
|
70
|
-
|
|
71
|
-
- artifacts written
|
|
72
|
-
- whether the embedded message-review safety-gate rules passed or returned
|
|
73
|
-
`revise-messaging`
|
|
74
|
-
- lead sample basis used
|
|
75
|
-
- proposed template and one sample message
|
|
76
|
-
- selected winner summary
|
|
77
|
-
- whether final reconciliation with `lead-filter.md` is complete or pending
|
|
78
|
-
|
|
79
|
-
Quality bar:
|
|
80
|
-
|
|
81
|
-
- Do not synthesize a lightweight message from general knowledge. The artifact
|
|
82
|
-
must prove the embedded message-review safety-gate workflow ran.
|
|
83
|
-
- There is no generate-message fast mode in this path. The embedded gate is the
|
|
84
|
-
same campaign-launch quality contract used by the parent-thread compatibility
|
|
85
|
-
path, not a lower-quality shortcut.
|
|
86
|
-
- Message generation can start before `lead-filter.md`, but message review
|
|
87
|
-
cannot start until the parent verifies the selected basis rows still pass the
|
|
88
|
-
final filter.
|
|
89
|
-
|
|
90
|
-
## Embedded Message Review Safety Gate
|
|
91
|
-
|
|
92
|
-
Use this campaign-launch subset to produce a truthful first-send message,
|
|
93
|
-
rendered token examples, and a decision without loading the full long-form
|
|
94
|
-
message prompt.
|
|
95
|
-
|
|
96
|
-
Required `message-validation.md` sections:
|
|
97
|
-
|
|
98
|
-
- `Status`
|
|
99
|
-
- `Mode`
|
|
100
|
-
- `Lead Sample Basis`
|
|
101
|
-
- `Strongest Reply Reason`
|
|
102
|
-
- `Campaign Element Pool`
|
|
103
|
-
- `Gold Standard Strategy Map`
|
|
104
|
-
- `Current Campaign Translation`
|
|
105
|
-
- `Token Fill Rules`
|
|
106
|
-
- `Token Adherence Table`
|
|
107
|
-
- `Angle Drafts`
|
|
108
|
-
- `Kill / Combine Review`
|
|
109
|
-
- `Finalizer Pass`
|
|
110
|
-
- `Gold-Standard Quality Gate`
|
|
111
|
-
- `Skeptical Prospect Review`
|
|
112
|
-
- `Winner Gate`
|
|
113
|
-
- `Selected Winner`
|
|
114
|
-
- `Findings`
|
|
115
|
-
- `Recommendation`
|
|
116
|
-
|
|
117
|
-
Quality gates:
|
|
3
|
+
Your job starts only after the source is approved and the bounded review batch
|
|
4
|
+
exists in the campaign table. Work only on the message-generation branch. Do not
|
|
5
|
+
source leads, create lead filters, import leads, confirm lead lists, queue cells,
|
|
6
|
+
attach sequences, start campaigns, ask the user questions, or mutate live
|
|
7
|
+
campaign state. The main thread owns approval and campaign writes.
|
|
118
8
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
-
|
|
127
|
-
|
|
9
|
+
## Source Of Truth
|
|
10
|
+
|
|
11
|
+
Use the live campaign inputs supplied by the parent thread:
|
|
12
|
+
|
|
13
|
+
- `campaignId`
|
|
14
|
+
- `campaignBrief` / campaign brief content model
|
|
15
|
+
- selected source decision and provider state
|
|
16
|
+
- `selectedLeadListId` or selected source list context
|
|
17
|
+
- `workflowTableId`
|
|
18
|
+
- imported review-batch rows from that selected list
|
|
19
|
+
- any already-saved fit/rubric result summaries supplied by the parent
|
|
20
|
+
|
|
21
|
+
Do not require or hunt for `brief.md`, `lead-review.md`, or `lead-sample.json`.
|
|
22
|
+
Those files are optional debug context only when the parent explicitly provides
|
|
23
|
+
them. Never inspect the product database directly, never run `psql`, and never
|
|
24
|
+
read stale local markdown files to reconstruct campaign state.
|
|
25
|
+
|
|
26
|
+
## Required First Steps
|
|
27
|
+
|
|
28
|
+
1. Load the full long-form generate-messages prompt:
|
|
29
|
+
|
|
30
|
+
`get_subskill_prompt({ subskillName: "generate-messages", offset, limit })`
|
|
31
|
+
until `hasMore` is false.
|
|
32
|
+
|
|
33
|
+
2. Use that prompt as the drafting contract. The create-campaign safety gate may
|
|
34
|
+
be used as an approval checklist, but it does not replace the long prompt.
|
|
35
|
+
3. Draft only from the campaign brief, selected source context, and imported
|
|
36
|
+
review-batch rows supplied by the parent.
|
|
37
|
+
4. Keep the work provisional until the user chooses `Use Template` in Messages.
|
|
38
|
+
|
|
39
|
+
## Owned Output
|
|
40
|
+
|
|
41
|
+
Return the following to the parent thread:
|
|
42
|
+
|
|
43
|
+
- proposed first-message template using supported `{{...}}` tokens
|
|
44
|
+
- token fill rules and fallbacks
|
|
45
|
+
- one rendered good-fill sample for a plausible passing review-batch row
|
|
46
|
+
- one omit/fallback sample when the row signal is not safe
|
|
47
|
+
- pass/fail notes against the generate-messages quality gates
|
|
48
|
+
|
|
49
|
+
Write `message-validation.md`, `message-prep.md`, or
|
|
50
|
+
`message-candidate-drafts.md` only when the parent explicitly asks for debug
|
|
51
|
+
artifacts. Normal live campaign runs can return the same content directly.
|
|
52
|
+
|
|
53
|
+
## Hard Rules
|
|
54
|
+
|
|
55
|
+
- Do not call product Generate Message cells. This worker drafts the template
|
|
56
|
+
recommendation only.
|
|
57
|
+
- Do not call `update_campaign_brief`; the main thread writes the approved
|
|
58
|
+
template after user approval.
|
|
59
|
+
- Do not overwrite an existing approved message/template.
|
|
60
|
+
- Do not use unsupported reply-rate, meeting-rate, ROI, revenue, or
|
|
61
|
+
customer-logo claims.
|
|
128
62
|
- Do not use internal tokens such as `{{profile_signal}}` in customer-facing
|
|
129
63
|
copy.
|
|
130
64
|
- Do not put bracketed instructions in the message body, such as `[ROW_BRIDGE]`,
|
|
131
65
|
`[insert]`, or `[generated]`.
|
|
132
|
-
- Optional row-specific personalization must be grounded in a row field or
|
|
133
|
-
omitted entirely.
|
|
134
66
|
- Engagement-source personalization is a special case, not the default opener.
|
|
135
67
|
Do not write `saw you {{engagement_context}} on {{post_context}}`, `saw you
|
|
136
68
|
reacted to`, `saw you engaging with`, or equivalent source-citation copy as a
|
|
137
|
-
default hook. Only refer to
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
69
|
+
default hook. Only refer to engagement when the line is self-aware and
|
|
70
|
+
low-certainty, for example: `not sure if this is too specific, but the
|
|
71
|
+
[topic] thread felt close enough to send`. Otherwise omit the engagement
|
|
72
|
+
signal and use role/company/problem context.
|
|
73
|
+
- The selected winner is one first outbound send only. No post-accept DM,
|
|
74
|
+
follow-up, cadence branch, sequence copy, or launch copy.
|
|
75
|
+
|
|
76
|
+
## Final Response
|
|
77
|
+
|
|
78
|
+
Return a concise status with:
|
|
79
|
+
|
|
80
|
+
- prompt basis loaded: `generate-messages`
|
|
81
|
+
- live campaign basis used
|
|
82
|
+
- proposed template
|
|
83
|
+
- token fill rules/fallbacks
|
|
84
|
+
- one rendered passing-row sample
|
|
85
|
+
- one rendered omit/fallback sample
|
|
86
|
+
- quality-gate pass/fail summary
|
|
87
|
+
- whether final template review is ready or needs revision
|
package/agents/registry.json
CHANGED
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
"Glob",
|
|
47
47
|
"mcp__sellable__get_provider_prompt",
|
|
48
48
|
"mcp__sellable__search_signals",
|
|
49
|
+
"mcp__sellable__select_promising_posts",
|
|
49
50
|
"mcp__sellable__fetch_post_engagers"
|
|
50
51
|
]
|
|
51
52
|
}
|
|
@@ -205,14 +206,20 @@
|
|
|
205
206
|
"displayName": "Message Draft Builder",
|
|
206
207
|
"target": "generate-messages",
|
|
207
208
|
"inputs": [
|
|
208
|
-
"
|
|
209
|
-
"
|
|
210
|
-
"
|
|
209
|
+
"campaignId",
|
|
210
|
+
"campaignBrief",
|
|
211
|
+
"selected source state",
|
|
212
|
+
"selectedLeadListId",
|
|
213
|
+
"workflowTableId",
|
|
214
|
+
"imported review-batch rows"
|
|
211
215
|
],
|
|
212
216
|
"producesArtifacts": [
|
|
213
|
-
"
|
|
217
|
+
"template recommendation",
|
|
218
|
+
"token fill rules",
|
|
219
|
+
"rendered sample"
|
|
214
220
|
],
|
|
215
221
|
"optionalProducesArtifacts": [
|
|
222
|
+
"message-validation.md",
|
|
216
223
|
"message-prep.md",
|
|
217
224
|
"message-candidate-drafts.md"
|
|
218
225
|
],
|
package/dist/tools/cells.js
CHANGED
|
@@ -20,7 +20,7 @@ export const cellToolDefinitions = [
|
|
|
20
20
|
},
|
|
21
21
|
{
|
|
22
22
|
name: "queue_cells",
|
|
23
|
-
description: "Queue cells for processing
|
|
23
|
+
description: "Queue explicit cells for processing. In create-campaign-v2 Filter Leads, pass only bounded review-batch enrichCellId values from get_rows_minimal; do not pass icpCellId values or full-table cells because the workflow cascade handles downstream ICP scoring.",
|
|
24
24
|
inputSchema: {
|
|
25
25
|
type: "object",
|
|
26
26
|
properties: {
|
package/dist/tools/prompts.d.ts
CHANGED
|
@@ -99,7 +99,9 @@ export interface SourceScoutRegistryResponse {
|
|
|
99
99
|
export interface PostFindLeadsScoutRegistryResponse {
|
|
100
100
|
version: number;
|
|
101
101
|
trigger: "find_leads_source_approved";
|
|
102
|
-
requiredArtifacts
|
|
102
|
+
requiredArtifacts?: string[];
|
|
103
|
+
requiredInputs?: string[];
|
|
104
|
+
optionalDebugArtifacts?: string[];
|
|
103
105
|
scouts: Array<{
|
|
104
106
|
id: string;
|
|
105
107
|
name: string;
|
|
@@ -123,7 +125,9 @@ export interface PostFindLeadsScoutRegistryResponse {
|
|
|
123
125
|
}>;
|
|
124
126
|
joinGate: {
|
|
125
127
|
afterAllComplete: boolean;
|
|
126
|
-
requiredArtifacts
|
|
128
|
+
requiredArtifacts?: string[];
|
|
129
|
+
requiredState?: string[];
|
|
130
|
+
optionalDebugArtifacts?: string[];
|
|
127
131
|
show: string[];
|
|
128
132
|
nextStage: string;
|
|
129
133
|
};
|
package/dist/tools/prompts.js
CHANGED
|
@@ -242,9 +242,9 @@ export function getSourceScoutRegistry() {
|
|
|
242
242
|
legacy: agent.legacy,
|
|
243
243
|
})),
|
|
244
244
|
usage: {
|
|
245
|
-
codex: "
|
|
246
|
-
claude: "Invoke
|
|
247
|
-
parentThreadRule: "Named agents are optional acceleration. If they are absent, do not customer-surface install status; run the same provider probes with MCP tools from the parent thread. Do not preload every provider prompt before spawning agents; each scout loads only the provider prompt for its lane.",
|
|
245
|
+
codex: "Source scouting is sequential by default. Launch multiple returned `name` values in one assistant turn only when the user asked for comparison, a prior lane failed, or the active flow marks the first lane borderline.",
|
|
246
|
+
claude: "Source scouting is sequential by default. Invoke multiple Task/Agent subagents with subagent_type equal to returned `name` values only when comparison, fallback, or borderline-source conditions apply.",
|
|
247
|
+
parentThreadRule: "Named agents are optional acceleration. If they are absent, do not customer-surface install status; run the same provider probes with MCP tools from the parent thread. Default fallback order: Signal Discovery / LinkedIn engagement, then Sales Nav recent activity, then broader Sales Nav title search, then Prospeo account/contact search. Do not preload every provider prompt before spawning agents; each scout loads only the provider prompt for its lane.",
|
|
248
248
|
},
|
|
249
249
|
};
|
|
250
250
|
}
|
|
@@ -254,7 +254,14 @@ export function getPostFindLeadsScoutRegistry() {
|
|
|
254
254
|
return {
|
|
255
255
|
version: registry.version,
|
|
256
256
|
trigger: "find_leads_source_approved",
|
|
257
|
-
|
|
257
|
+
requiredInputs: [
|
|
258
|
+
"campaignId",
|
|
259
|
+
"campaignBrief",
|
|
260
|
+
"source decision and selectedLeadList/source state",
|
|
261
|
+
"workflowTableId",
|
|
262
|
+
"imported review-batch rows from selectedLeadList",
|
|
263
|
+
],
|
|
264
|
+
optionalDebugArtifacts: ["brief.md", "lead-review.md", "lead-sample.json"],
|
|
258
265
|
scouts: scouts.map((agent) => ({
|
|
259
266
|
id: String(agent.id || ""),
|
|
260
267
|
name: String(agent.name || ""),
|
|
@@ -282,14 +289,15 @@ export function getPostFindLeadsScoutRegistry() {
|
|
|
282
289
|
})),
|
|
283
290
|
joinGate: {
|
|
284
291
|
afterAllComplete: true,
|
|
285
|
-
|
|
292
|
+
requiredState: ["leadScoringRubrics", "messageDraftRecommendation"],
|
|
293
|
+
optionalDebugArtifacts: ["lead-filter.md", "message-validation.md"],
|
|
286
294
|
show: ["readable_filters_with_reasons", "sample_message_for_approval"],
|
|
287
295
|
nextStage: "message-review",
|
|
288
296
|
},
|
|
289
297
|
usage: {
|
|
290
298
|
codex: "After the user approves or auto-confirms the lead source, spawn both returned scout `name` values in one assistant turn only when the current Codex host exposes those custom agents.",
|
|
291
299
|
claude: "After lead source approval, invoke both returned Task/Agent subagents in one assistant message only when the current Claude session lists those agents, so filter-leads and message generation run concurrently.",
|
|
292
|
-
parentThreadRule: "Named agents are optional acceleration. If they are absent, do not customer-surface install status; the main thread still orchestrates filter and message branches from
|
|
300
|
+
parentThreadRule: "Named agents are optional acceleration. If they are absent, do not customer-surface install status; the main thread still orchestrates filter and message branches from CampaignOffer state, selected source state, workflowTableId, and imported review-batch rows. Debug markdown/json artifacts are optional only. The message branch must load the full generate-messages prompt and may use the create-campaign-v2 message-review safety gate as a supplemental approval check. Join before message review.",
|
|
293
301
|
},
|
|
294
302
|
};
|
|
295
303
|
}
|
package/package.json
CHANGED
|
@@ -13,7 +13,6 @@ allowed-tools:
|
|
|
13
13
|
- mcp__sellable__get_provider_prompt
|
|
14
14
|
- mcp__sellable__get_source_scout_registry
|
|
15
15
|
- mcp__sellable__get_post_find_leads_scout_registry
|
|
16
|
-
- mcp__sellable__get_message_prompt
|
|
17
16
|
- mcp__sellable__get_active_workspace
|
|
18
17
|
- mcp__sellable__list_senders
|
|
19
18
|
- mcp__sellable__get_sender
|
|
@@ -71,10 +70,11 @@ Disk artifacts are optional debug/UAT diagnostics; normal customer runs should
|
|
|
71
70
|
not create, link, or surface local draft files unless the user explicitly asks
|
|
72
71
|
for them. Resume, gating, and handoff read campaign state first. The
|
|
73
72
|
watchable campaign exists after the short brief; lead import is bounded to the
|
|
74
|
-
first review batch. After that, the user chooses whether to use filters or skip
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
73
|
+
first review batch. After that, the user chooses whether to use filters or skip.
|
|
74
|
+
When filters are chosen, save rubrics, then pause before queueing enrichment or
|
|
75
|
+
filtering: tell the user the fit rules are saved, the message template needs
|
|
76
|
+
approval next, and enrichment/filtering will start after that approval. Use
|
|
77
|
+
Template is the default message path; AI Generated is only an explicit opt-out.
|
|
78
78
|
|
|
79
79
|
## Opening Turn Contract
|
|
80
80
|
|
|
@@ -148,12 +148,13 @@ calls `get_post_find_leads_scout_registry`, then launches the returned
|
|
|
148
148
|
filter-leads scout and message-generation scout together when real subagents are
|
|
149
149
|
available and the current session exposes the returned names. Message
|
|
150
150
|
generation is the provisional Message Draft Builder: it may start after the
|
|
151
|
-
review batch exists, including while the user is on filter choice, but
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
MCP
|
|
151
|
+
review batch exists, including while the user is on filter choice, but workflow
|
|
152
|
+
cell execution must wait. After rubrics are saved, do not queue enrichment,
|
|
153
|
+
filtering, or Generate Message cells until the user approves the message
|
|
154
|
+
template. AI Generated is an explicit opt-out that cancels or ignores the
|
|
155
|
+
background template draft. If the post-lead agents are absent, the main thread
|
|
156
|
+
still orchestrates the same branches from the compact context with MCP
|
|
157
|
+
tools/assets.
|
|
157
158
|
|
|
158
159
|
Use rendered Markdown for user review surfaces, not fenced code blocks. Keep
|
|
159
160
|
lines short, use indexed section labels and bullets, and translate internal
|
|
@@ -561,24 +562,26 @@ updates.
|
|
|
561
562
|
asset loader so they share the same config.
|
|
562
563
|
3. Follow that prompt and workflow config exactly.
|
|
563
564
|
4. For message generation, use the `post-find-leads-message-scout` agent when
|
|
564
|
-
available
|
|
565
|
-
|
|
566
|
-
`
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
565
|
+
available. The worker and parent-thread fallback must load the full
|
|
566
|
+
long-form `generate-messages` prompt with
|
|
567
|
+
`mcp__sellable__get_subskill_prompt({ subskillName: "generate-messages", offset, limit })`
|
|
568
|
+
until `hasMore=false`. The create-campaign message-review safety gate is a
|
|
569
|
+
supplemental approval checklist, not a replacement for the long prompt. Use
|
|
570
|
+
campaign state, campaign brief content, selected source state, and imported
|
|
571
|
+
review-batch rows as the source of truth; do not read stale local markdown,
|
|
572
|
+
inspect the database directly, or synthesize `message-validation.md` from
|
|
572
573
|
general knowledge.
|
|
573
574
|
5. Create the campaign shell early with the v1 brief so the user can open the
|
|
574
575
|
watch link and see useful setup state immediately. Import only the first
|
|
575
576
|
bounded review batch after the source is attached to the campaign; do not
|
|
576
577
|
queue workflow cells, attach a sequence, or start until the filter choice is
|
|
577
|
-
resolved,
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
578
|
+
resolved, rubrics are saved when filters are enabled, template/token rules
|
|
579
|
+
are approved on the default Use Template path, and the approved message set
|
|
580
|
+
is synced into the campaign brief. After rubrics save, pause and say the fit
|
|
581
|
+
rules are saved; approve the message template next; after approval, queue the
|
|
582
|
+
bounded review-batch `enrichCellId` cells to kick off enrichment/filtering.
|
|
583
|
+
Product Generate Message cells must not run from the background template
|
|
584
|
+
path before that template/token approval.
|
|
582
585
|
Do not ask the user to approve the brief before shell creation unless they
|
|
583
586
|
explicitly requested a no-write draft; the shell itself is the review surface.
|
|
584
587
|
6. The main thread owns watch navigation. Call
|
|
@@ -571,29 +571,19 @@ until the filter choice is resolved and you choose Use Template.`
|
|
|
571
571
|
provisional candidate work from probable good-fit rows in `lead-sample.json`,
|
|
572
572
|
but the final `message-validation.md` winner must cite basis rows from
|
|
573
573
|
`lead-sample.json` that still pass `lead-filter.md`.
|
|
574
|
-
- Parallel means real parallel execution, not optimistic progress copy.
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
each scout loads only its own provider prompt. If host subagents are
|
|
588
|
-
unavailable or the names are not visible, use the same provider probes via
|
|
589
|
-
independent MCP/tool calls in the parent thread or dedicated Sellable MCP
|
|
590
|
-
tools that perform server-side `Promise.all` fan-out. Do not write "source
|
|
591
|
-
scout agents are not installed" or similar host status into customer-facing
|
|
592
|
-
output. If real parallel execution is not available or not allowed, run the
|
|
593
|
-
same DAG sequentially and use honest copy: `I’ll tighten the filter first,
|
|
594
|
-
then draft the message from the same sample.` Never say `kicking off two
|
|
595
|
-
workstreams`, `in parallel`, or `background` unless parallel branches were
|
|
596
|
-
actually launched.
|
|
574
|
+
- Parallel means real parallel execution, not optimistic progress copy. Source
|
|
575
|
+
scouting is sequential by default: start with the first recommended lane from
|
|
576
|
+
`flow.v2.json`, usually Signal Discovery / LinkedIn engagement. Only launch
|
|
577
|
+
multiple named source scouts when the user explicitly requested comparison, a
|
|
578
|
+
prior lane failed, or the active flow marks the first lane borderline. The
|
|
579
|
+
fallback order is plain: use Sales Nav to find ICP people who are actively
|
|
580
|
+
posting on LinkedIn; if that is not enough, search Sales Nav by titles; if
|
|
581
|
+
that is still not enough, use Prospeo for a broader account/contact path.
|
|
582
|
+
Before any source scout dispatch, call `get_source_scout_registry` and use the
|
|
583
|
+
returned canonical `name` values. The parent thread should not preload every
|
|
584
|
+
provider prompt; each scout loads only its own provider prompt. Do not write
|
|
585
|
+
"source scout agents are not installed" or similar host status into
|
|
586
|
+
customer-facing output.
|
|
597
587
|
- Source scout parallelism must not hide all provider work from the watch UI.
|
|
598
588
|
The parent thread owns the first visible provider search: call the chosen
|
|
599
589
|
provider prompt/search with the minted CampaignOffer id and provider
|
|
@@ -633,22 +623,25 @@ batch`, and a no-launch safety note. Do not leave the guide saying
|
|
|
633
623
|
recovery and ask whether to retry import, import more from the approved
|
|
634
624
|
source, or revise source. Active filtering starts only after rubrics are
|
|
635
625
|
saved; do not say filtering the batch before rubrics are saved.
|
|
636
|
-
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
626
|
+
- When the user chooses filters, immediately persist `enableICPFilters: true`
|
|
627
|
+
and `currentStep: "create-icp-rubric"` so the watched app leaves the filter
|
|
628
|
+
choice screen and shows that Codex is defining the rules in chat. After Lead
|
|
629
|
+
Fit Builder saves rubrics, move the watched browser to Filter Leads before
|
|
630
|
+
waiting for message work to finish. Persist `currentStep:
|
|
631
|
+
"apply-icp-rubric"` and `watchNarration.stage: "fit-message"`, then read the
|
|
632
|
+
bounded review batch with `get_rows_minimal`, but do not queue workflow cells
|
|
633
|
+
yet. Tell the user the fit rules are saved, the message template needs
|
|
634
|
+
approval next, and enrichment/filtering will start after approval. Do not call
|
|
635
|
+
`check_rubric` in the normal create-campaign-v2 path. Use Template is the
|
|
636
|
+
default message path. AI Generated is an explicit opt-out that cancels or
|
|
643
637
|
ignores the background template draft and must not let late template output
|
|
644
638
|
overwrite campaign state. Product Generate Message cells should not run from
|
|
645
639
|
the background template path until template/token rules are approved. After
|
|
646
640
|
message approval, update the campaign brief with an Approved Message Template
|
|
647
|
-
containing `{{...}}` tokens and keep `enableICPFilters: true`;
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
and Settings/sender/sequence handoff.
|
|
641
|
+
containing `{{...}}` tokens and keep `enableICPFilters: true`; then queue only
|
|
642
|
+
pending/error `enrichCellId` values with `queue_cells` to start enrichment and
|
|
643
|
+
filtering. Generate Message detects template mode from those tokens, not from
|
|
644
|
+
`useMessagingTemplate`.
|
|
652
645
|
- During pre-import validation, do not call `check_rubric`; use the lead-filter
|
|
653
646
|
artifacts and only use campaign-backed scoring after Step 13 imports the
|
|
654
647
|
15-lead test batch.
|
|
@@ -1283,21 +1276,22 @@ Do not:
|
|
|
1283
1276
|
|
|
1284
1277
|
Step 3 is the Message Draft Builder path. It is orchestrated by the main thread
|
|
1285
1278
|
and executed either by the `post-find-leads-message-scout` worker or by the
|
|
1286
|
-
parent-thread fallback. The worker
|
|
1287
|
-
|
|
1288
|
-
reference
|
|
1279
|
+
parent-thread fallback. The worker and fallback must load the full
|
|
1280
|
+
`generate-messages` prompt with `get_subskill_prompt` and use it as the drafting
|
|
1281
|
+
contract. The small safety-gate reference is only a supplemental approval
|
|
1282
|
+
check, not a replacement for the long message workflow:
|
|
1289
1283
|
|
|
1290
1284
|
```
|
|
1285
|
+
mcp__sellable__get_subskill_prompt({ subskillName: "generate-messages", offset, limit }) until hasMore=false
|
|
1291
1286
|
mcp__sellable__get_subskill_asset({ subskillName: "create-campaign-v2", assetPath: "references/message-review-safety-gate.md" })
|
|
1292
1287
|
```
|
|
1293
1288
|
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
into the main thread.
|
|
1289
|
+
Use campaign state, campaign brief content, selected source state, and the
|
|
1290
|
+
selected/imported review-batch rows as the source of truth. Do not read
|
|
1291
|
+
`brief.md`, `lead-review.md`, or `lead-sample.json` as required state in the
|
|
1292
|
+
normal live campaign path; those files are optional debug context only. If the
|
|
1293
|
+
long prompt plus safety gate cannot safely approve the draft, stop at
|
|
1294
|
+
`revise-messaging` with the exact failure.
|
|
1301
1295
|
|
|
1302
1296
|
Do NOT proceed to Step 4 (message review gate) unless the user has answered
|
|
1303
1297
|
filter choice, the Messages step has shown the mode choice, the user chose Use
|
|
@@ -230,31 +230,24 @@ setting: `~/.codex/config.toml` with
|
|
|
230
230
|
|
|
231
231
|
## Parallelism + Naming
|
|
232
232
|
|
|
233
|
-
Source
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
Code,
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
subagents. When asking the user to approve a brief with Sellable finding leads,
|
|
252
|
-
use an explicit label like `Approve brief + use background source scouts` only
|
|
253
|
-
when the current runtime exposes the named agents; otherwise use `Approve brief
|
|
254
|
-
|
|
255
|
-
- compare source paths`. If the host runs them sequentially or the named agents
|
|
256
|
-
are absent, keep the output numeric but do not claim the source scout was
|
|
257
|
-
parallel or surface install status to the customer.
|
|
233
|
+
Source selection is sequential by default. Start with the first recommended
|
|
234
|
+
source lane from `flow.v2.json`; for the current campaign shape that is usually
|
|
235
|
+
Signal Discovery / LinkedIn engagement. Only try the next fallback after the
|
|
236
|
+
current lane is not viable, the user asks for a comparison, or the first lane is
|
|
237
|
+
borderline and needs a second source to avoid a bad recommendation. The fallback
|
|
238
|
+
order must stay plain: use Sales Nav to find ICP people who are actively posting
|
|
239
|
+
on LinkedIn; if that is not enough, search Sales Nav by titles; if that is still
|
|
240
|
+
not enough, use Prospeo for a broader account/contact path.
|
|
241
|
+
|
|
242
|
+
Source-angle comparison should be real, not implied. Call
|
|
243
|
+
`get_source_scout_registry` before dispatching source scouts and use the
|
|
244
|
+
returned canonical `name` values. In Codex or Claude Code, launch multiple named
|
|
245
|
+
source scouts in the same turn only when the user explicitly requested source
|
|
246
|
+
comparison, a prior lane failed, or the active flow marks the first lane as
|
|
247
|
+
borderline. The parent thread should not fetch every provider prompt first; each
|
|
248
|
+
scout loads only its matching provider prompt. If source work is sequential,
|
|
249
|
+
keep the output numeric but do not claim the source scout was parallel or
|
|
250
|
+
surface install status to the customer.
|
|
258
251
|
|
|
259
252
|
For post-lead work, call `get_post_find_leads_scout_registry` after source
|
|
260
253
|
approval and use the returned canonical `name` values. Launch both returned
|
|
@@ -963,9 +963,10 @@
|
|
|
963
963
|
"targetLeadCountFromConfig": "sourceTargetGoodFitLeadCount (default 300) for provider source-list materialization, not import.importLimit",
|
|
964
964
|
"signalDiscoveryRequiredFields": [
|
|
965
965
|
"targetEngagerCount from approved source math",
|
|
966
|
-
"
|
|
966
|
+
"approved promoted post ids selected with select_promising_posts",
|
|
967
|
+
"maxPostsToScrape from approved source math"
|
|
967
968
|
],
|
|
968
|
-
"signalDiscoveryRule": "For Signal Discovery, pass targetEngagerCount = ceil(sourceTargetGoodFitLeads / sampledFitRateAfterCleanup) and maxPostsToScrape = postsNeeded
|
|
969
|
+
"signalDiscoveryRule": "For Signal Discovery, promote/select the exact approved posts with select_promising_posts before import_leads. Then pass targetEngagerCount = ceil(sourceTargetGoodFitLeads / sampledFitRateAfterCleanup) and maxPostsToScrape = postsNeeded from the approved source math. If no approved promoted posts are attached to the campaign, stop and route back to find-leads; do not import from unpromoted sample/search results. The first campaign review batch is still limited by confirm_lead_list targetLeadCount import.importLimit.",
|
|
969
970
|
"onZeroLeads": "escalate_hard_fail",
|
|
970
971
|
"modeAddHandshake": {
|
|
971
972
|
"firstCallReturns": "needsModeSelection=true + existingLeadListId",
|
|
@@ -976,7 +977,8 @@
|
|
|
976
977
|
"defaultBranch": "normal-discovery",
|
|
977
978
|
"skipWhen": "resolved source branch returns sourceLeadListId for confirm_lead_list",
|
|
978
979
|
"requiredBeforeCall": [
|
|
979
|
-
"campaign_attached_source_state"
|
|
980
|
+
"campaign_attached_source_state",
|
|
981
|
+
"for Signal Discovery: approved_promoted_posts_attached_to_campaign"
|
|
980
982
|
]
|
|
981
983
|
},
|
|
982
984
|
{
|
|
@@ -1069,11 +1071,7 @@
|
|
|
1069
1071
|
"review_batch_imported": "filter-choice",
|
|
1070
1072
|
"escalation_triggered": "escalation"
|
|
1071
1073
|
},
|
|
1072
|
-
"requiredArtifacts": [
|
|
1073
|
-
"brief.md",
|
|
1074
|
-
"lead-review.md",
|
|
1075
|
-
"lead-sample.json"
|
|
1076
|
-
],
|
|
1074
|
+
"requiredArtifacts": [],
|
|
1077
1075
|
"requiredCampaignState": [
|
|
1078
1076
|
"campaignId",
|
|
1079
1077
|
"providerSearchAssociation",
|
|
@@ -1102,7 +1100,18 @@
|
|
|
1102
1100
|
"currentStep": "filter-choice",
|
|
1103
1101
|
"watchNarration.stage": "fit-message"
|
|
1104
1102
|
},
|
|
1105
|
-
"watchNarrationRule": "
|
|
1103
|
+
"watchNarrationRule": "Ask whether the user wants to further filter the imported leads. Say whether the selected lead list looks mixed/good/noisy based on the imported 15-row review batch, then ask Choose filters or skip. Do not say filtering the batch before rubrics are saved."
|
|
1104
|
+
},
|
|
1105
|
+
{
|
|
1106
|
+
"action": "persist_filters_enabled_choice",
|
|
1107
|
+
"tool": "update_campaign",
|
|
1108
|
+
"when": "immediately after the user chooses filters_enabled",
|
|
1109
|
+
"requiredValues": {
|
|
1110
|
+
"enableICPFilters": true,
|
|
1111
|
+
"currentStep": "create-icp-rubric",
|
|
1112
|
+
"watchNarration.stage": "fit-message"
|
|
1113
|
+
},
|
|
1114
|
+
"watchNarrationRule": "Move the watched app to Filter Rules and show passive copy that Codex is defining the filters in chat. Do not leave the user on filter-choice after they choose filters."
|
|
1106
1115
|
}
|
|
1107
1116
|
],
|
|
1108
1117
|
"allowedTools": [
|
|
@@ -1136,6 +1145,8 @@
|
|
|
1136
1145
|
"interruptOnly": true,
|
|
1137
1146
|
"requiredCampaignState": [
|
|
1138
1147
|
"campaignId",
|
|
1148
|
+
"campaignBrief",
|
|
1149
|
+
"selectedLeadListId",
|
|
1139
1150
|
"workflowTableId"
|
|
1140
1151
|
]
|
|
1141
1152
|
},
|
|
@@ -1158,9 +1169,9 @@
|
|
|
1158
1169
|
"name": "filter-leads",
|
|
1159
1170
|
"target": "filter-leads",
|
|
1160
1171
|
"inputs": [
|
|
1161
|
-
"
|
|
1162
|
-
"
|
|
1163
|
-
"
|
|
1172
|
+
"campaignBrief",
|
|
1173
|
+
"selected source decision",
|
|
1174
|
+
"selectedLeadListId",
|
|
1164
1175
|
"workflowTableId review-batch rows"
|
|
1165
1176
|
],
|
|
1166
1177
|
"producesArtifacts": [
|
|
@@ -1176,30 +1187,33 @@
|
|
|
1176
1187
|
"target": "generate-messages",
|
|
1177
1188
|
"mode": "DRY MODE",
|
|
1178
1189
|
"inputs": [
|
|
1179
|
-
"
|
|
1180
|
-
"
|
|
1181
|
-
"
|
|
1190
|
+
"campaignBrief",
|
|
1191
|
+
"selected source decision",
|
|
1192
|
+
"selectedLeadListId",
|
|
1182
1193
|
"workflowTableId review-batch rows"
|
|
1183
1194
|
],
|
|
1184
1195
|
"producesArtifacts": [
|
|
1185
|
-
"
|
|
1196
|
+
"template recommendation",
|
|
1197
|
+
"token fill rules",
|
|
1198
|
+
"rendered sample"
|
|
1186
1199
|
],
|
|
1187
1200
|
"optionalProducesArtifacts": [
|
|
1201
|
+
"message-validation.md",
|
|
1188
1202
|
"message-prep.md",
|
|
1189
1203
|
"message-candidate-drafts.md"
|
|
1190
1204
|
],
|
|
1191
1205
|
"ownership": "proof inventory, token strategy, angle drafting, skeptical-prospect review, and selected winner only"
|
|
1192
1206
|
}
|
|
1193
1207
|
],
|
|
1194
|
-
"earlyMessageStartRule": "After auto-execute-leads confirms the 15-row review batch, workflowTableId is ready, and the user has reached filter choice, the Message Draft Builder may start from
|
|
1195
|
-
"finalMessageReconcileRule": "message
|
|
1208
|
+
"earlyMessageStartRule": "After auto-execute-leads confirms the 15-row review batch, workflowTableId is ready, and the user has reached filter choice, the Message Draft Builder may start from campaignBrief, selected source state, selectedLeadListId, and imported campaign table rows, including while the user is on filter choice. This background template draft is provisional speed work only. The message worker must load the full generate-messages prompt; parent-thread fallback loads the same prompt and may use references/message-review-safety-gate.md only as a supplemental approval checklist. Legacy/resume preview prep still requires at least 3 probable good-fit rows. It may run beside filter-leads, but product Generate Message cells cannot queue until save_rubrics and update_campaign_brief both succeed.",
|
|
1209
|
+
"finalMessageReconcileRule": "The message recommendation may start before lead-filter.md exists, but before message-review it must cite only imported review-batch rows that still pass the saved rubric/filter results. If the selected winner depends on a row later excluded by saved filters, revise message-generation before message review.",
|
|
1196
1210
|
"finalTemplateReviewLockRule": "cannot start template review until filter choice is answered and the user chooses Use Template in Messages. If filters are enabled, lock template review until saved rubrics exist, a bounded filter run has completed, and there are usable passing/probably passing rows. prefer at least 2 usable passing rows for template review; if only 1 passes, show weak-sample copy and ask whether to continue, revise, import more, or skip filters. If filters are skipped, route to Messages mode choice once the review batch is ready. AI Generated is an explicit opt-out and must cancel or ignore the background template draft.",
|
|
1197
1211
|
"claudeRule": "In Claude Code, launch both returned post-find-leads scouts with Task/Agent subagents in the same assistant message only when the current session lists those agent names. Do not run filter first and then message generation unless subagents/background work are unavailable.",
|
|
1198
1212
|
"codexRule": "In Codex, launch both returned post-find-leads scout names as disjoint subagents in the same assistant turn only when the host exposes those custom agents for this run. If the host cannot spawn them, run the same branches sequentially and say so.",
|
|
1199
1213
|
"fallback": "If real parallel branches are unavailable or the named agents are absent, run filter-leads and then message-generation in the parent thread with product MCP tools/assets. Do not customer-surface agent install status, and do not claim background or parallel work in that fallback."
|
|
1200
1214
|
},
|
|
1201
1215
|
{
|
|
1202
|
-
"action": "
|
|
1216
|
+
"action": "wait_for_lead_filter_rules",
|
|
1203
1217
|
"requiredArtifacts": [
|
|
1204
1218
|
"lead-filter.md"
|
|
1205
1219
|
],
|
|
@@ -1209,7 +1223,7 @@
|
|
|
1209
1223
|
"message-prep.md",
|
|
1210
1224
|
"message-candidate-drafts.md"
|
|
1211
1225
|
],
|
|
1212
|
-
"rule": "Do not wait for message-validation.md before saving rubrics and moving the watched browser to Filter Leads. Message work may still be running while the user watches fit filtering."
|
|
1226
|
+
"rule": "Do not wait for message-validation.md before saving rubrics and moving the watched browser to Filter Leads. lead-filter.md is a debug artifact name; the durable requirement is production-safe rubric rules derived from the live campaign table review batch. Message work may still be running while the user watches fit filtering."
|
|
1213
1227
|
},
|
|
1214
1228
|
{
|
|
1215
1229
|
"action": "save_filter_rubrics_to_campaign",
|
|
@@ -1247,11 +1261,35 @@
|
|
|
1247
1261
|
"when": "after_save_rubrics_succeeds_before_waiting_for_message_validation",
|
|
1248
1262
|
"writesCampaignState": "currentStep:apply-icp-rubric"
|
|
1249
1263
|
},
|
|
1264
|
+
{
|
|
1265
|
+
"tool": "get_rows_minimal",
|
|
1266
|
+
"requiredValues": {
|
|
1267
|
+
"tableId": "workflowTableId",
|
|
1268
|
+
"limit": "import.importLimit"
|
|
1269
|
+
},
|
|
1270
|
+
"purpose": "read_bounded_review_batch_cell_ids_before_filter_wait",
|
|
1271
|
+
"requiredBeforeCascade": true
|
|
1272
|
+
},
|
|
1273
|
+
{
|
|
1274
|
+
"tool": "queue_cells",
|
|
1275
|
+
"requiredValues": {
|
|
1276
|
+
"tableId": "workflowTableId",
|
|
1277
|
+
"cellSource": "bounded_review_batch_enrichCellIds",
|
|
1278
|
+
"statusFilter": [
|
|
1279
|
+
"pending",
|
|
1280
|
+
"error",
|
|
1281
|
+
"dependency_blocked"
|
|
1282
|
+
]
|
|
1283
|
+
},
|
|
1284
|
+
"purpose": "queue_bounded_review_batch_enrichment_before_waiting_for_rubric_results",
|
|
1285
|
+
"rule": "Queue only enrichCellId values from get_rows_minimal for the bounded review batch. Do not queue icpCellId values or whole-table cells; the workflow cascade runs ICP scoring after enrichment."
|
|
1286
|
+
},
|
|
1250
1287
|
{
|
|
1251
1288
|
"tool": "wait_for_rubric_results",
|
|
1252
1289
|
"requiredValues": {
|
|
1253
1290
|
"includeRows": false,
|
|
1254
|
-
"minPassedCount": 1
|
|
1291
|
+
"minPassedCount": 1,
|
|
1292
|
+
"targetCount": "bounded review batch count"
|
|
1255
1293
|
},
|
|
1256
1294
|
"purpose": "wait_for_bounded_filter_run_before_messages_mode",
|
|
1257
1295
|
"readVia": "stats_only_tool_result",
|
|
@@ -1269,22 +1307,21 @@
|
|
|
1269
1307
|
"optional": true
|
|
1270
1308
|
},
|
|
1271
1309
|
{
|
|
1272
|
-
"action": "
|
|
1273
|
-
"
|
|
1274
|
-
"
|
|
1310
|
+
"action": "wait_for_message_draft_recommendation",
|
|
1311
|
+
"requiredOutputs": [
|
|
1312
|
+
"template recommendation",
|
|
1313
|
+
"token fill rules",
|
|
1314
|
+
"rendered sample"
|
|
1275
1315
|
],
|
|
1276
1316
|
"optionalArtifacts": [
|
|
1317
|
+
"message-validation.md",
|
|
1277
1318
|
"message-prep.md",
|
|
1278
1319
|
"message-candidate-drafts.md"
|
|
1279
1320
|
],
|
|
1280
|
-
"reconciliationRule": "Before entering message-review, verify
|
|
1321
|
+
"reconciliationRule": "Before entering message-review, verify the recommendation came from the same campaignBrief, selected source state, selectedLeadListId, imported review-batch rows, and saved filters. Saved filters gate the sample rows; debug markdown files are optional only."
|
|
1281
1322
|
}
|
|
1282
1323
|
],
|
|
1283
|
-
"requiredArtifacts": [
|
|
1284
|
-
"brief.md",
|
|
1285
|
-
"lead-review.md",
|
|
1286
|
-
"lead-sample.json"
|
|
1287
|
-
],
|
|
1324
|
+
"requiredArtifacts": [],
|
|
1288
1325
|
"producesArtifacts": [
|
|
1289
1326
|
"lead-filter.md",
|
|
1290
1327
|
"message-validation.md"
|
|
@@ -1299,6 +1336,8 @@
|
|
|
1299
1336
|
"get_subskill_asset",
|
|
1300
1337
|
"get_post_find_leads_scout_registry",
|
|
1301
1338
|
"save_rubrics",
|
|
1339
|
+
"get_rows_minimal",
|
|
1340
|
+
"queue_cells",
|
|
1302
1341
|
"wait_for_rubric_results",
|
|
1303
1342
|
"update_campaign",
|
|
1304
1343
|
"get_campaign_navigation_state",
|
|
@@ -1309,16 +1348,16 @@
|
|
|
1309
1348
|
],
|
|
1310
1349
|
"toolRules": [
|
|
1311
1350
|
"The post-lead workstreams are disjoint: filter-leads owns lead-filter.md/rubric.json; message-generation owns message-validation.md/message-prep.md/message-candidate-drafts.md.",
|
|
1312
|
-
"message-generation can start before
|
|
1351
|
+
"message-generation can start before saved filters, but message-review cannot start until saved filters and the message recommendation reconcile against the same imported review-batch rows.",
|
|
1313
1352
|
"Do not let filter-leads create a new message sample. Do not let message-generation fetch new prospects.",
|
|
1314
|
-
"Before writing message-validation.md
|
|
1315
|
-
"Do not queue
|
|
1353
|
+
"Before writing message-validation.md or returning a template recommendation, message-generation must load the full get_subskill_prompt({ subskillName: \"generate-messages\" }) prompt and use campaignBrief, selected source state, selectedLeadListId, and imported review-batch rows as the source of truth. Optional debug markdown files are not durable state.",
|
|
1354
|
+
"Do not queue before saved rubrics. After save_rubrics succeeds, queue only bounded review-batch enrichCellId values from get_rows_minimal before wait_for_rubric_results.",
|
|
1355
|
+
"Do not attach sequence, start, or queue product Generate Message cells until the approved message set is synced into campaignBrief."
|
|
1316
1356
|
],
|
|
1317
1357
|
"doNotAllow": [
|
|
1318
1358
|
"create_campaign",
|
|
1319
1359
|
"import_leads",
|
|
1320
1360
|
"confirm_lead_list",
|
|
1321
|
-
"queue_cells",
|
|
1322
1361
|
"start_campaign",
|
|
1323
1362
|
"check_rubric",
|
|
1324
1363
|
"generate_messages",
|
|
@@ -1343,6 +1382,8 @@
|
|
|
1343
1382
|
"interruptOnly": true,
|
|
1344
1383
|
"requiredCampaignState": [
|
|
1345
1384
|
"campaignId",
|
|
1385
|
+
"campaignBrief",
|
|
1386
|
+
"selectedLeadListId",
|
|
1346
1387
|
"workflowTableId"
|
|
1347
1388
|
],
|
|
1348
1389
|
"debugProducesArtifacts": [
|
|
@@ -1363,9 +1404,9 @@
|
|
|
1363
1404
|
"tool": "update_campaign",
|
|
1364
1405
|
"requiredValues": {
|
|
1365
1406
|
"currentStep": "messages",
|
|
1366
|
-
"watchNarration.stage": "
|
|
1407
|
+
"watchNarration.stage": "fit-message"
|
|
1367
1408
|
},
|
|
1368
|
-
"watchNarrationRule": "Messages first shows a mode choice: Use Template and AI Generated. Use Template is recommended because it uses the approved campaign brief and review-batch evidence. AI Generated is an explicit opt-out from the background template draft."
|
|
1409
|
+
"watchNarrationRule": "Messages first shows a mode choice, not final review: Use Template and AI Generated. Use Template is recommended because it uses the approved campaign brief and review-batch evidence. AI Generated is an explicit opt-out from the background template draft. Do not show Review fit and message until the user chooses a mode and a reviewable message/template exists."
|
|
1369
1410
|
},
|
|
1370
1411
|
{
|
|
1371
1412
|
"action": "show_messages_mode_choice",
|
|
@@ -1430,6 +1471,8 @@
|
|
|
1430
1471
|
"interruptOnly": true,
|
|
1431
1472
|
"requiredCampaignState": [
|
|
1432
1473
|
"campaignId",
|
|
1474
|
+
"campaignBrief",
|
|
1475
|
+
"selectedLeadListId",
|
|
1433
1476
|
"workflowTableId"
|
|
1434
1477
|
]
|
|
1435
1478
|
},
|
|
@@ -1557,40 +1600,37 @@
|
|
|
1557
1600
|
"onEnter": [
|
|
1558
1601
|
{
|
|
1559
1602
|
"action": "run_or_reconcile_subskill",
|
|
1560
|
-
"target": "
|
|
1603
|
+
"target": "generate-messages",
|
|
1561
1604
|
"mode": "DRY MODE",
|
|
1562
|
-
"sampleSource": "
|
|
1605
|
+
"sampleSource": "imported review-batch rows from selectedLeadListId",
|
|
1563
1606
|
"toolCallRequiredBeforeArtifacts": [
|
|
1564
|
-
"
|
|
1607
|
+
"get_subskill_prompt({ subskillName: \"generate-messages\", offset, limit }) until hasMore=false",
|
|
1608
|
+
"optional supplemental check: get_subskill_asset({ subskillName: \"create-campaign-v2\", assetPath: \"references/message-review-safety-gate.md\" })"
|
|
1565
1609
|
],
|
|
1566
|
-
"
|
|
1567
|
-
"reconcileWith": "
|
|
1610
|
+
"skipIfFreshStateExists": "fresh messageDraftRecommendation from the same campaign/source/review-batch basis",
|
|
1611
|
+
"reconcileWith": "saved filters and imported review-batch rows; optional lead-filter.md only mirrors those filters"
|
|
1568
1612
|
},
|
|
1569
1613
|
{
|
|
1570
|
-
"action": "
|
|
1571
|
-
"
|
|
1614
|
+
"action": "return_template_recommendation",
|
|
1615
|
+
"optionalArtifact": "message-validation.md"
|
|
1572
1616
|
}
|
|
1573
1617
|
],
|
|
1574
|
-
"requiredArtifacts": [
|
|
1575
|
-
"brief.md",
|
|
1576
|
-
"lead-review.md",
|
|
1577
|
-
"lead-sample.json"
|
|
1578
|
-
],
|
|
1618
|
+
"requiredArtifacts": [],
|
|
1579
1619
|
"producesArtifacts": [
|
|
1580
1620
|
"message-validation.md"
|
|
1581
1621
|
],
|
|
1582
1622
|
"allowedTools": [
|
|
1623
|
+
"get_subskill_prompt",
|
|
1583
1624
|
"get_subskill_asset",
|
|
1584
1625
|
"AskUserQuestion",
|
|
1585
1626
|
"request_user_input"
|
|
1586
1627
|
],
|
|
1587
1628
|
"toolRules": [
|
|
1588
|
-
"Before writing message-validation.md, message-review.md, or a message-review AskUserQuestion,
|
|
1589
|
-
"
|
|
1590
|
-
"Do not hand-write message-validation.md from message-prep.md, message-candidate-drafts.md, or general campaign knowledge.",
|
|
1591
|
-
"message-validation.md must prove the
|
|
1592
|
-
"If the
|
|
1593
|
-
"Do not load the full generate-messages subskill in create-campaign-v2. If the safety gate is missing a needed campaign-specific rule or the first safety-gate draft fails quality gates, route to revise-messaging with the concrete failure instead of loading the long prompt.",
|
|
1629
|
+
"Before writing message-validation.md, message-review.md, or a message-review AskUserQuestion, load the full get_subskill_prompt({ subskillName: \"generate-messages\" }) prompt and draft from campaignBrief, selected source state, selectedLeadListId, and imported review-batch rows.",
|
|
1630
|
+
"Do not use brief.md, lead-review.md, or lead-sample.json as required live state; those files are optional debug context only.",
|
|
1631
|
+
"Do not hand-write message-validation.md from message-prep.md, message-candidate-drafts.md, stale markdown files, database reads, or general campaign knowledge.",
|
|
1632
|
+
"message-validation.md or the returned recommendation must prove the generate-messages workflow ran and include Token Fill Rules, good-fill and omit/fallback examples, a raw sendable selected winner, and quality gate notes before message-review can recommend approve-message.",
|
|
1633
|
+
"If the generate-messages output is plausible but weaker than the gold-standard rules, stop at message-review with revise-messaging. Do not continue to approval or mint just because the mechanical flow worked.",
|
|
1594
1634
|
"The approved message set must be written back into campaignBrief before auto-execute-messaging observes or queues product Generate Message cells. AI Generated mode uses the product's AI-generated path instead of template review."
|
|
1595
1635
|
],
|
|
1596
1636
|
"doNotAllow": [
|
|
@@ -1628,6 +1668,8 @@
|
|
|
1628
1668
|
"interruptOnly": true,
|
|
1629
1669
|
"requiredCampaignState": [
|
|
1630
1670
|
"campaignId",
|
|
1671
|
+
"campaignBrief",
|
|
1672
|
+
"selectedLeadListId",
|
|
1631
1673
|
"workflowTableId"
|
|
1632
1674
|
]
|
|
1633
1675
|
},
|
|
@@ -1638,15 +1680,18 @@
|
|
|
1638
1680
|
"resumeOnly": false,
|
|
1639
1681
|
"onEnter": [
|
|
1640
1682
|
{
|
|
1641
|
-
"action": "
|
|
1642
|
-
"
|
|
1643
|
-
"
|
|
1644
|
-
"
|
|
1645
|
-
"
|
|
1646
|
-
"
|
|
1647
|
-
"
|
|
1683
|
+
"action": "read_live_message_recommendation",
|
|
1684
|
+
"requiredState": [
|
|
1685
|
+
"campaignBrief",
|
|
1686
|
+
"selected source state",
|
|
1687
|
+
"selectedLeadListId",
|
|
1688
|
+
"workflowTableId",
|
|
1689
|
+
"saved filters when filters are enabled",
|
|
1690
|
+
"template recommendation with token fill rules and rendered sample"
|
|
1648
1691
|
],
|
|
1649
|
-
"
|
|
1692
|
+
"optionalDebugFiles": [
|
|
1693
|
+
"lead-filter.md",
|
|
1694
|
+
"message-validation.md",
|
|
1650
1695
|
"message-prep.md",
|
|
1651
1696
|
"message-candidate-drafts.md"
|
|
1652
1697
|
]
|
|
@@ -1765,8 +1810,8 @@
|
|
|
1765
1810
|
"requires": [
|
|
1766
1811
|
"campaignId",
|
|
1767
1812
|
"message-review-decision.md",
|
|
1768
|
-
"
|
|
1769
|
-
"
|
|
1813
|
+
"approved template recommendation",
|
|
1814
|
+
"saved filters when filters are enabled"
|
|
1770
1815
|
],
|
|
1771
1816
|
"when": "after_message_approved_before_product_messaging",
|
|
1772
1817
|
"fields": [
|
|
@@ -192,9 +192,9 @@ After review batch import:
|
|
|
192
192
|
```json
|
|
193
193
|
{
|
|
194
194
|
"stage": "fit-message",
|
|
195
|
-
"headline": "
|
|
196
|
-
"visibleState": "The first review batch is in the campaign.",
|
|
197
|
-
"agentIntent": "Codex is asking you to
|
|
195
|
+
"headline": "Do you want filters?",
|
|
196
|
+
"visibleState": "The first review batch is in the campaign. The list is ready to decide whether extra filtering is worth it.",
|
|
197
|
+
"agentIntent": "Codex is asking whether you want to further filter these leads before message review. The Message Draft Builder may prepare a template in the background, but review waits until the filter path is settled.",
|
|
198
198
|
"nextAction": "Choose filters or skip",
|
|
199
199
|
"safety": "Nothing enriches, validates, or sends until the message is ready and approved.",
|
|
200
200
|
"workerStatuses": {
|
|
@@ -207,8 +207,9 @@ After review batch import:
|
|
|
207
207
|
Use this after the selected review rows are present and before filters are
|
|
208
208
|
saved. This is add-filters intent, not active filtering. Tell the user to
|
|
209
209
|
Choose filters or skip, and do not say filtering the batch before rubrics are
|
|
210
|
-
saved.
|
|
211
|
-
|
|
210
|
+
saved. When the user chooses filters, immediately persist
|
|
211
|
+
`enableICPFilters: true` and move to `create-icp-rubric` so the watched app
|
|
212
|
+
shows Filter Rules while Codex defines the rules in chat.
|
|
212
213
|
|
|
213
214
|
Fit + message:
|
|
214
215
|
|
|
@@ -51,9 +51,13 @@ Create and save a comprehensive lead scoring rubric that:
|
|
|
51
51
|
|
|
52
52
|
## Rubric Validation + Results
|
|
53
53
|
|
|
54
|
-
- `
|
|
54
|
+
- `mcp__sellable__get_rows_minimal` - Read bounded review-batch cell IDs
|
|
55
|
+
- `mcp__sellable__queue_cells` - Queue only bounded `enrichCellId` values
|
|
55
56
|
- `mcp__sellable__wait_for_rubric_results` - Poll pass-rate results
|
|
56
57
|
|
|
58
|
+
`check_rubric` is legacy/recovery only. Do not use it in normal
|
|
59
|
+
create-campaign-v2 runs.
|
|
60
|
+
|
|
57
61
|
</tools>
|
|
58
62
|
|
|
59
63
|
<rubric_structure>
|
|
@@ -117,7 +121,7 @@ Required fields:
|
|
|
117
121
|
|
|
118
122
|
- If **Keep & apply**:
|
|
119
123
|
- Call `update_campaign({ campaignId, enableICPFilters: true, currentStep: "apply-icp-rubric" })`
|
|
120
|
-
- Then proceed to Phase 5 (
|
|
124
|
+
- Then proceed to Phase 5 (queue bounded enrichment cells + wait for score results).
|
|
121
125
|
|
|
122
126
|
**If no campaignOfferId:**
|
|
123
127
|
Ask: "Which campaign should I create the rubric for? You can share the campaign ID or describe the target audience."
|
|
@@ -203,7 +207,9 @@ update_campaign({
|
|
|
203
207
|
|
|
204
208
|
This triggers the campaign sync and moves the user to the filter-leads step where they can see the campaign table with scoring columns.
|
|
205
209
|
|
|
206
|
-
|
|
210
|
+
For normal create-campaign-v2 runs, the caller should immediately queue only the
|
|
211
|
+
bounded review-batch enrichment cells and wait for scores. For standalone
|
|
212
|
+
rubric editing, ask the user if we should kick off enrichment for a sample:
|
|
207
213
|
|
|
208
214
|
"ICP filtering enabled — you should see the leads table with scoring columns now. Want me to run enrichment on the first 5 leads to check pass rates?"
|
|
209
215
|
|
|
@@ -212,9 +218,14 @@ Then ask the user if we should kick off enrichment for a sample:
|
|
|
212
218
|
|
|
213
219
|
## Phase 5: Enrich + Score a Sample
|
|
214
220
|
|
|
215
|
-
1. Call `
|
|
216
|
-
|
|
217
|
-
|
|
221
|
+
1. Call `get_rows_minimal({ tableId, limit: 5 })` or use the caller-provided
|
|
222
|
+
bounded review-batch rows.
|
|
223
|
+
2. Call `queue_cells({ tableId, cellIds })` with only pending/error
|
|
224
|
+
`enrichCellId` values. Do not pass `icpCellId` values or full-table cells;
|
|
225
|
+
the workflow cascade handles downstream ICP scoring after enrichment.
|
|
226
|
+
3. Call `wait_for_rubric_results` with `targetCount: 5` and `minPassedCount: 1`
|
|
227
|
+
— polls until ICP scores land.
|
|
228
|
+
4. Summarize pass rate (`passed/completed`, percent) and recommend:
|
|
218
229
|
- Tighten filters if pass rate is too high (>80% — too loose).
|
|
219
230
|
- Loosen filters if pass rate is too low (<20% — too strict).
|
|
220
231
|
- Continue when results look healthy (30-70% is typical).
|