@sellable/mcp 0.1.0
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/.claude-plugin/plugin.json +12 -0
- package/.mcp.json +9 -0
- package/README.md +355 -0
- package/dist/api.d.ts +21 -0
- package/dist/api.js +73 -0
- package/dist/auth.d.ts +60 -0
- package/dist/auth.js +246 -0
- package/dist/engage-memory.d.ts +63 -0
- package/dist/engage-memory.js +354 -0
- package/dist/index-dev.d.ts +2 -0
- package/dist/index-dev.js +17 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +8 -0
- package/dist/server.d.ts +1 -0
- package/dist/server.js +499 -0
- package/dist/skills.d.ts +11 -0
- package/dist/skills.js +97 -0
- package/dist/tools/auth.d.ts +30 -0
- package/dist/tools/auth.js +124 -0
- package/dist/tools/blueprint-commit.d.ts +174 -0
- package/dist/tools/blueprint-commit.js +286 -0
- package/dist/tools/bootstrap.d.ts +64 -0
- package/dist/tools/bootstrap.js +246 -0
- package/dist/tools/campaigns.d.ts +589 -0
- package/dist/tools/campaigns.js +892 -0
- package/dist/tools/cells.d.ts +58 -0
- package/dist/tools/cells.js +48 -0
- package/dist/tools/context.d.ts +88 -0
- package/dist/tools/context.js +271 -0
- package/dist/tools/csv-domains.d.ts +73 -0
- package/dist/tools/csv-domains.js +464 -0
- package/dist/tools/csv-linkedin.d.ts +102 -0
- package/dist/tools/csv-linkedin.js +712 -0
- package/dist/tools/direct-campaigns.d.ts +240 -0
- package/dist/tools/direct-campaigns.js +250 -0
- package/dist/tools/engage-bootstrap.d.ts +94 -0
- package/dist/tools/engage-bootstrap.js +205 -0
- package/dist/tools/engage-discovery.d.ts +78 -0
- package/dist/tools/engage-discovery.js +150 -0
- package/dist/tools/engage-memory.d.ts +181 -0
- package/dist/tools/engage-memory.js +143 -0
- package/dist/tools/engage-state.d.ts +72 -0
- package/dist/tools/engage-state.js +62 -0
- package/dist/tools/enrichment.d.ts +167 -0
- package/dist/tools/enrichment.js +174 -0
- package/dist/tools/flow-preflight.d.ts +68 -0
- package/dist/tools/flow-preflight.js +138 -0
- package/dist/tools/framework.d.ts +44 -0
- package/dist/tools/framework.js +153 -0
- package/dist/tools/interaction-mode.d.ts +27 -0
- package/dist/tools/interaction-mode.js +102 -0
- package/dist/tools/leads.d.ts +2417 -0
- package/dist/tools/leads.js +2307 -0
- package/dist/tools/linkedin.d.ts +210 -0
- package/dist/tools/linkedin.js +229 -0
- package/dist/tools/navigation.d.ts +91 -0
- package/dist/tools/navigation.js +381 -0
- package/dist/tools/one-off.d.ts +229 -0
- package/dist/tools/one-off.js +273 -0
- package/dist/tools/processing.d.ts +70 -0
- package/dist/tools/processing.js +56 -0
- package/dist/tools/prompts.d.ts +211 -0
- package/dist/tools/prompts.js +210 -0
- package/dist/tools/provider-preflight.d.ts +21 -0
- package/dist/tools/provider-preflight.js +59 -0
- package/dist/tools/readiness.d.ts +261 -0
- package/dist/tools/readiness.js +510 -0
- package/dist/tools/rows.d.ts +126 -0
- package/dist/tools/rows.js +105 -0
- package/dist/tools/rubrics.d.ts +497 -0
- package/dist/tools/rubrics.js +681 -0
- package/dist/tools/senders.d.ts +44 -0
- package/dist/tools/senders.js +69 -0
- package/dist/tools/sequencer.d.ts +127 -0
- package/dist/tools/sequencer.js +194 -0
- package/dist/tools/tables.d.ts +35 -0
- package/dist/tools/tables.js +36 -0
- package/dist/tools/verify-row.d.ts +36 -0
- package/dist/tools/verify-row.js +38 -0
- package/dist/tools/workspaces.d.ts +140 -0
- package/dist/tools/workspaces.js +139 -0
- package/dist/utils/workspace-root.d.ts +1 -0
- package/dist/utils/workspace-root.js +39 -0
- package/package.json +46 -0
- package/skills/building-gtm-tables/SKILL.md +216 -0
- package/skills/building-gtm-tables/core/auto-execute.yaml +19 -0
- package/skills/building-gtm-tables/core/blueprint-schema.json +72 -0
- package/skills/building-gtm-tables/references/brief-to-blueprint.md +334 -0
- package/skills/building-gtm-tables/references/column-type-catalog.md +318 -0
- package/skills/building-gtm-tables/references/common-blueprints.fixtures.ts +199 -0
- package/skills/building-gtm-tables/references/common-blueprints.md +44 -0
- package/skills/building-gtm-tables/references/failure-taxonomy.md +197 -0
- package/skills/building-gtm-tables/references/uat-seed-prompts.md +37 -0
- package/skills/building-gtm-tables/references/verify-loop.md +74 -0
- package/skills/campaign-messages/SKILL.md +173 -0
- package/skills/campaign-messages/flow.v1.json +75 -0
- package/skills/craft-message/SKILL.md +401 -0
- package/skills/create-campaign/ARCHITECTURE.md +232 -0
- package/skills/create-campaign/DISCUSS.md +296 -0
- package/skills/create-campaign/FLOW_ASCII.md +240 -0
- package/skills/create-campaign/HOST-PARITY-CHECKLIST.md +49 -0
- package/skills/create-campaign/README.md +142 -0
- package/skills/create-campaign/SKILL.md +286 -0
- package/skills/create-campaign/context/README.md +67 -0
- package/skills/create-campaign/context/_TEMPLATE.md +12 -0
- package/skills/create-campaign/context/context.md +35 -0
- package/skills/create-campaign/context/learnings.md +16 -0
- package/skills/create-campaign/context/registry.json +19 -0
- package/skills/create-campaign/core/flow.v1.json +217 -0
- package/skills/create-campaign/core/policy.md +191 -0
- package/skills/create-campaign/core/providers/apollo.json +35 -0
- package/skills/create-campaign/core/providers/prospeo.json +34 -0
- package/skills/create-campaign/core/providers/registry.json +31 -0
- package/skills/create-campaign/core/providers/sales-nav.json +37 -0
- package/skills/create-campaign/core/providers/signal-discovery.json +42 -0
- package/skills/create-campaign/references/brief-template.md +64 -0
- package/skills/create-campaign/references/campaign-quality.md +84 -0
- package/skills/create-campaign/references/copy-calibration-examples.md +120 -0
- package/skills/create-campaign/references/offer-patterns.md +108 -0
- package/skills/create-campaign/references/provider-selection-strategy.md +212 -0
- package/skills/create-campaign/references/question-examples.md +167 -0
- package/skills/create-campaign/references/token-fill-examples.md +81 -0
- package/skills/create-campaign-brief/ARCHITECTURE.md +72 -0
- package/skills/create-campaign-brief/DISCUSS.md +64 -0
- package/skills/create-campaign-brief/README.md +176 -0
- package/skills/create-campaign-brief/SKILL.md +537 -0
- package/skills/create-campaign-brief/references/brief-synthesis-rules.md +100 -0
- package/skills/create-campaign-brief/references/brief-template.md +220 -0
- package/skills/create-campaign-brief/references/campaign-idea-options.md +30 -0
- package/skills/create-campaign-brief/references/copy-appendix-template.md +62 -0
- package/skills/create-campaign-brief/references/draft-lifecycle.md +23 -0
- package/skills/create-campaign-brief/references/examples/MANIFEST.json +89 -0
- package/skills/create-campaign-brief/references/examples/briefs/clover.md +223 -0
- package/skills/create-campaign-brief/references/examples/briefs/galley.md +222 -0
- package/skills/create-campaign-brief/references/examples/briefs/gelee.md +220 -0
- package/skills/create-campaign-brief/references/examples/briefs/hey-digital.md +234 -0
- package/skills/create-campaign-brief/references/examples/briefs/persona.md +231 -0
- package/skills/create-campaign-brief/references/examples/briefs/revvix.md +220 -0
- package/skills/create-campaign-brief/references/examples/briefs/sellable-dev.md +220 -0
- package/skills/create-campaign-brief/references/examples/briefs/superposition.md +233 -0
- package/skills/create-campaign-brief/references/examples/briefs/superpower.md +219 -0
- package/skills/create-campaign-brief/references/examples/briefs/westpark-villas.md +220 -0
- package/skills/create-campaign-brief/references/icp-lock-question-bank.md +43 -0
- package/skills/create-campaign-brief/references/messaging-inputs.md +58 -0
- package/skills/create-campaign-brief/references/output-acceptance-rubric.md +62 -0
- package/skills/create-campaign-brief/references/phase75-active-runtime-message-pack.md +248 -0
- package/skills/create-campaign-brief/references/phase75-canonical-brief-template.md +319 -0
- package/skills/create-campaign-brief/references/phase75-good-brief-and-messaging-examples.md +445 -0
- package/skills/create-campaign-brief/references/quick-research-protocol.md +39 -0
- package/skills/create-campaign-brief/references/reference-sheet-protocol.md +60 -0
- package/skills/create-campaign-brief/references/zero-shot-iteration-rules.md +66 -0
- package/skills/create-campaign-v2/SKILL.md +1619 -0
- package/skills/create-campaign-v2/core/auto-execute.README.md +219 -0
- package/skills/create-campaign-v2/core/auto-execute.yaml +121 -0
- package/skills/create-campaign-v2/core/flow.v2.json +1643 -0
- package/skills/create-campaign-v2/core/policy.md +82 -0
- package/skills/create-campaign-v2/references/ai-tells.md +253 -0
- package/skills/create-campaign-v2/references/approval-gate-framing.md +346 -0
- package/skills/create-campaign-v2/references/draft-lifecycle.md +110 -0
- package/skills/create-campaign-v2/references/escalation-ladder.md +119 -0
- package/skills/create-campaign-v2/references/filter-leads.md +495 -0
- package/skills/create-campaign-v2/references/final-handoff-contract.md +176 -0
- package/skills/create-campaign-v2/references/gold-standard-message-examples.md +394 -0
- package/skills/create-campaign-v2/references/gold-standard-message-patterns.md +314 -0
- package/skills/create-campaign-v2/references/gold-standard-message-validation-example.md +212 -0
- package/skills/create-campaign-v2/references/lead-validation-preview.md +172 -0
- package/skills/create-campaign-v2/references/parallel-critique-protocol.md +368 -0
- package/skills/create-campaign-v2/references/sample-validation-loop.md +289 -0
- package/skills/create-campaign-v2/references/step-13-import-leads.md +151 -0
- package/skills/create-campaign-v2/references/step-15-re-cascade.md +90 -0
- package/skills/create-campaign-v2/references/thomas-revision-filters.md +521 -0
- package/skills/create-campaign-v2/references/thomas-variant-selection.md +202 -0
- package/skills/create-campaign-v2/references/tier-routing-matrix.md +66 -0
- package/skills/create-campaign-v2/references/validation-criteria.md +367 -0
- package/skills/create-campaign-v2/references/watch-link-handoff.md +106 -0
- package/skills/create-campaign-v2-validation/SKILL.md +296 -0
- package/skills/create-post/SKILL.md +1308 -0
- package/skills/create-rubric/SKILL.md +251 -0
- package/skills/engage/SKILL.md +549 -0
- package/skills/engage/core/README.md +23 -0
- package/skills/engage/core/proven-searches.json +11 -0
- package/skills/engage/core/style-guide.template.md +47 -0
- package/skills/engage/core/tracked-people.json +10 -0
- package/skills/enrich-prospects/SKILL.md +97 -0
- package/skills/find-leads/SKILL.md +467 -0
- package/skills/generate-messages/SKILL.md +2361 -0
- package/skills/interview/SKILL.md +132 -0
- package/skills/interview/core/ENGAGE_STYLE_GUIDE.template.md +54 -0
- package/skills/interview/core/ICP.template.md +54 -0
- package/skills/interview/core/VOICE_PROFILE.template.md +101 -0
- package/skills/providers/apollo.md +520 -0
- package/skills/providers/prospeo.md +398 -0
- package/skills/providers/sales-nav.md +372 -0
- package/skills/providers/signal-discovery.md +495 -0
- package/skills/research/SKILL.md +258 -0
- package/skills/research/config.json +9 -0
- package/skills/research/override.md +13 -0
- package/skills/research-prospect/SKILL.md +99 -0
- package/skills/research-sender/SKILL.md +158 -0
- package/skills/workflow-sequences/SKILL.md +85 -0
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# Thomas Variant Selection
|
|
2
|
+
|
|
3
|
+
This reference governs which rows in a Plan 85-03 critique sample earn
|
|
4
|
+
an Opus / craft-message rewrite. Load this file only when
|
|
5
|
+
`messaging.critique.enabled === true` AND
|
|
6
|
+
`messaging.critique.opus.enabled === true` in
|
|
7
|
+
`core/auto-execute.yaml`. When Opus is off, the protocol never
|
|
8
|
+
consults variant selection.
|
|
9
|
+
|
|
10
|
+
## Principle
|
|
11
|
+
|
|
12
|
+
Opus is reserved for the highest-value subset only. A critique pass
|
|
13
|
+
that sends every row to Opus defeats the cost model and blurs the
|
|
14
|
+
signal about what the plain generator already gets right. Variant
|
|
15
|
+
selection is a narrow filter on top of the bounded critique sample,
|
|
16
|
+
not a second sample.
|
|
17
|
+
|
|
18
|
+
The rule of thumb: if the plain generator shipped a message that's
|
|
19
|
+
"fine but not sharp" and the lead is unusually high value, Opus
|
|
20
|
+
earns its place. Otherwise, the synthesizer's rewrite is enough.
|
|
21
|
+
|
|
22
|
+
## When This File Loads
|
|
23
|
+
|
|
24
|
+
Load this file only when BOTH flags are on:
|
|
25
|
+
|
|
26
|
+
- `messaging.critique.enabled === true`
|
|
27
|
+
- `messaging.critique.opus.enabled === true`
|
|
28
|
+
|
|
29
|
+
Do not consult variant selection when Opus is off. Do not consult it
|
|
30
|
+
during Step 13, Step 14, or Step 16.
|
|
31
|
+
|
|
32
|
+
## Inputs
|
|
33
|
+
|
|
34
|
+
- The row being critiqued (lead row plus its plain generated message).
|
|
35
|
+
- The three critic envelopes for this row (targeting, copy, voice).
|
|
36
|
+
- `lead-sample.json` for the current cohort.
|
|
37
|
+
- `messaging.critique.opus.*` config values.
|
|
38
|
+
- The current Opus budget headroom (tracked across the pass).
|
|
39
|
+
|
|
40
|
+
## Hard Caps
|
|
41
|
+
|
|
42
|
+
Two caps that short-circuit selection before any analysis:
|
|
43
|
+
|
|
44
|
+
1. **`opus.maxMessagesPerPass`** (default 2). Once N rows have been
|
|
45
|
+
escalated to Opus in the current pass, every subsequent row falls
|
|
46
|
+
back to the non-Opus synthesis output regardless of how sharp the
|
|
47
|
+
selection signals are. Log `opus_cap_tripped` with the row id.
|
|
48
|
+
2. **`opus.budgetUsdCap`** (default 1.5 USD). Budget trip halts Opus
|
|
49
|
+
for the rest of this pass. Log `opus_budget_cap_tripped`. The
|
|
50
|
+
non-Opus critique continues on remaining rows.
|
|
51
|
+
|
|
52
|
+
If either cap is tripped at row N, variant selection short-circuits
|
|
53
|
+
to "no Opus" for rows N+1, N+2, ... of the current pass.
|
|
54
|
+
|
|
55
|
+
## Selection Signals
|
|
56
|
+
|
|
57
|
+
A row EARNS Opus only when the signals below point the same way. One
|
|
58
|
+
strong signal is not enough. Three is usually required unless a
|
|
59
|
+
single signal is a hard "buyer of buyers" marker.
|
|
60
|
+
|
|
61
|
+
### Signal 1 — Lead value tier
|
|
62
|
+
|
|
63
|
+
The lead row reads as high-value on the validated filter:
|
|
64
|
+
|
|
65
|
+
- Title matches the buyer role the brief calls out as the primary
|
|
66
|
+
decision-maker (not an adjacent influencer).
|
|
67
|
+
- Company size / stage matches the brief's ideal band (not merely
|
|
68
|
+
"in bucket").
|
|
69
|
+
- Company name is a named target account, or a logo the brief
|
|
70
|
+
treats as a proof marker for this motion.
|
|
71
|
+
|
|
72
|
+
Not high-value:
|
|
73
|
+
|
|
74
|
+
- Generic IC title at a bucket-match company.
|
|
75
|
+
- Right function but visibly wrong stage (pre-seed when brief says
|
|
76
|
+
Series B+).
|
|
77
|
+
- Company that barely passed the filter on a weak supporting rule.
|
|
78
|
+
|
|
79
|
+
### Signal 2 — Critic divergence toward "revise"
|
|
80
|
+
|
|
81
|
+
The three critic envelopes disagree about how to fix the plain
|
|
82
|
+
message, and at least two of them have `verdict = "revise"` with
|
|
83
|
+
substantive `revisions[*]`. In other words: the plain message
|
|
84
|
+
clearly has room, and the critics can SEE what's missing — but the
|
|
85
|
+
synthesizer's merge is likely to be a compromise rather than a
|
|
86
|
+
clean rewrite.
|
|
87
|
+
|
|
88
|
+
Not a divergence signal:
|
|
89
|
+
|
|
90
|
+
- All three critics said `keep`. The plain message is already good;
|
|
91
|
+
Opus would over-polish.
|
|
92
|
+
- One critic said `reject` and the other two said `keep`. The
|
|
93
|
+
rewrite is a fallback case, not a high-value upgrade case.
|
|
94
|
+
- Two critics said `revise` but their revisions point at the same
|
|
95
|
+
sentence. The synthesizer can merge that cleanly.
|
|
96
|
+
|
|
97
|
+
### Signal 3 — Personalization upside
|
|
98
|
+
|
|
99
|
+
The lead row carries a rich per-lead signal that the plain
|
|
100
|
+
generator only partially used:
|
|
101
|
+
|
|
102
|
+
- A per-lead post, hire, or visible tool the brief supports but the
|
|
103
|
+
plain opener didn't reference.
|
|
104
|
+
- A named account the brief lists as a named target.
|
|
105
|
+
- An event the brief's proof inventory can anchor to but the plain
|
|
106
|
+
message settled for a generic hook.
|
|
107
|
+
|
|
108
|
+
Not personalization upside:
|
|
109
|
+
|
|
110
|
+
- Plain message already anchored on the per-lead signal.
|
|
111
|
+
- The lead has no per-lead signal; only category-level personalization
|
|
112
|
+
is available.
|
|
113
|
+
- The richest signal in the row is a field the brief doesn't support
|
|
114
|
+
(proposing a NEW token — that path is operator review, not Opus).
|
|
115
|
+
|
|
116
|
+
### Signal 4 — Motion sharpness payoff
|
|
117
|
+
|
|
118
|
+
The matched motion is one where a crafted rewrite visibly changes
|
|
119
|
+
buyer response (proof-led specialist, stack-replacement, job-post
|
|
120
|
+
signal). Event-led and signal-led motions where the hook is already
|
|
121
|
+
concrete rarely need Opus — the plain generator's hook carries.
|
|
122
|
+
|
|
123
|
+
Not a sharpness signal:
|
|
124
|
+
|
|
125
|
+
- Fallback motion with a weak hook. Opus won't rescue a motion-
|
|
126
|
+
mismatched draft; send it back to the brief instead.
|
|
127
|
+
- Event-led motion where the plain message's opener already nailed
|
|
128
|
+
the event.
|
|
129
|
+
|
|
130
|
+
## Selection Rule
|
|
131
|
+
|
|
132
|
+
A row earns Opus only when:
|
|
133
|
+
|
|
134
|
+
- At least three of the four signals above point toward high value
|
|
135
|
+
AND at least one signal is Signal 1 (lead value tier), OR
|
|
136
|
+
- Signal 1 is a hard "named target account or logo-tier buyer" marker,
|
|
137
|
+
AND at least one other signal is positive.
|
|
138
|
+
|
|
139
|
+
If neither clause is true, the row uses the non-Opus synthesizer
|
|
140
|
+
output. Log `opus_not_selected` with the row id and the signals
|
|
141
|
+
considered.
|
|
142
|
+
|
|
143
|
+
## Selection Output
|
|
144
|
+
|
|
145
|
+
When a row is selected for Opus, the critique protocol:
|
|
146
|
+
|
|
147
|
+
1. Checks the Opus budget and count caps. If either is tripped,
|
|
148
|
+
skip Opus for this row (and subsequent rows in this pass) and
|
|
149
|
+
keep the non-Opus rewrite.
|
|
150
|
+
2. Runs `craft_message(row, synthesis_rewrite, critics_out)`.
|
|
151
|
+
3. Applies the SAME token-contract enforcement to the Opus output
|
|
152
|
+
that it applies to any synthesis output:
|
|
153
|
+
- `rejectOnFakeProof` — invented proof forces fallback.
|
|
154
|
+
- `rejectOnUnsupportedToken` — unsupported token forces fallback.
|
|
155
|
+
- `synthesis.enforceFinalizerPass` — finalizer pass must pass.
|
|
156
|
+
4. On pass, persists the Opus rewrite for that row. On fail, falls
|
|
157
|
+
back to the non-Opus rewrite (and if that also failed, to the
|
|
158
|
+
plain message).
|
|
159
|
+
5. Logs `opus_selected` (with signals) on entry and
|
|
160
|
+
`opus_rewrite_persisted` / `opus_rewrite_rejected` on exit.
|
|
161
|
+
|
|
162
|
+
## What Opus Is NOT Allowed To Do
|
|
163
|
+
|
|
164
|
+
Opus does not get a different token contract. Every rule that binds
|
|
165
|
+
the plain generator and the non-Opus synthesizer binds Opus too:
|
|
166
|
+
|
|
167
|
+
- Use only supported tokens from the validated brief.
|
|
168
|
+
- No invented metric, logo, customer, funding detail, or product claim.
|
|
169
|
+
- No personalization that can't be traced to `lead-sample.json`.
|
|
170
|
+
- No new proposed token promoted into the persisted rewrite.
|
|
171
|
+
- Same shape rules: one-sentence-per-line body, PS earns its place,
|
|
172
|
+
no resume-list PS, no jargon a 5th-grade reader can't parse.
|
|
173
|
+
|
|
174
|
+
An Opus rewrite that breaks any of these is a silent fallback, not
|
|
175
|
+
a win.
|
|
176
|
+
|
|
177
|
+
## Fallback Priority
|
|
178
|
+
|
|
179
|
+
When multiple rewrite layers are in play, the persisted message
|
|
180
|
+
follows this priority (first passing wins):
|
|
181
|
+
|
|
182
|
+
1. Opus rewrite (if selected AND token-contract-clean AND budget
|
|
183
|
+
available).
|
|
184
|
+
2. Non-Opus synthesis rewrite (if token-contract-clean AND
|
|
185
|
+
finalizer-clean).
|
|
186
|
+
3. Plain generated message (always a valid fallback).
|
|
187
|
+
|
|
188
|
+
The plain message is NEVER skipped in favor of a broken rewrite.
|
|
189
|
+
|
|
190
|
+
## Hard Rules
|
|
191
|
+
|
|
192
|
+
- Opus is off by default. Variant selection is never consulted when
|
|
193
|
+
Opus is off.
|
|
194
|
+
- A row earns Opus only when multiple selection signals align. One
|
|
195
|
+
signal is not enough unless it's a named-target or logo-tier Signal
|
|
196
|
+
1.
|
|
197
|
+
- `opus.maxMessagesPerPass` and `opus.budgetUsdCap` are hard caps.
|
|
198
|
+
Once tripped, the rest of the pass runs non-Opus.
|
|
199
|
+
- Opus is bound by the same token contract as the plain generator
|
|
200
|
+
and the non-Opus synthesizer.
|
|
201
|
+
- Token-contract-clean Opus > non-Opus synthesis > plain message,
|
|
202
|
+
in that fallback order. Never persist a broken rewrite.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Tier Routing Matrix
|
|
2
|
+
|
|
3
|
+
This reference governs `attach_recommended_sequence` routing decisions
|
|
4
|
+
made at Step 16 (`awaiting-user-greenlight`). Load before calling
|
|
5
|
+
`attach_recommended_sequence` and on every resume into Step 16.
|
|
6
|
+
|
|
7
|
+
## Principle
|
|
8
|
+
|
|
9
|
+
The sequence template a campaign uses depends on the sender's LinkedIn
|
|
10
|
+
tier. Premium / SalesNav senders have InMail access on open profiles;
|
|
11
|
+
Standard senders do not and must go through invite → accept → DM.
|
|
12
|
+
|
|
13
|
+
The tail reads the sender's current tier + synced limits (via the
|
|
14
|
+
sender-limits sync path fixed in commit `4002b8878`) and picks the
|
|
15
|
+
right template automatically. Operators can override on the campaign
|
|
16
|
+
builder UI but the autonomous tail default is this matrix.
|
|
17
|
+
|
|
18
|
+
## Matrix
|
|
19
|
+
|
|
20
|
+
| Sender tier | Template | Fallback | Notes |
|
|
21
|
+
| ----------------------------------- | ---------------------- | ----------------------------------------- | -------------------------------------- |
|
|
22
|
+
| **Premium InMail** | `INMAIL_OPEN` | `INVITE → DM` if open profile check fails | Direct InMail on open profiles |
|
|
23
|
+
| **Sales Navigator Core / Advanced** | `INMAIL_OPEN` | `INVITE → DM` if credit exhausted | Open profile + InMail credits |
|
|
24
|
+
| **Sales Navigator Advanced Plus** | `INMAIL_OPEN` | `INVITE → DM` | Team seat, same InMail path |
|
|
25
|
+
| **LinkedIn Premium Business** | `INMAIL_OPEN` | `INVITE → DM` | Personal Premium tier |
|
|
26
|
+
| **LinkedIn Standard (no Premium)** | `INVITE → accept → DM` | (none; must go invite path) | Cannot send InMail; must connect first |
|
|
27
|
+
|
|
28
|
+
## Tier detection
|
|
29
|
+
|
|
30
|
+
Tier is detected via `enrichProfile` on the sender's LinkedIn URL. The
|
|
31
|
+
response includes `liTier` (one of `PREMIUM_INMAIL`, `SALES_NAVIGATOR_CORE`,
|
|
32
|
+
`SALES_NAVIGATOR_ADVANCED`, `SALES_NAVIGATOR_ADVANCED_PLUS`,
|
|
33
|
+
`PREMIUM_BUSINESS`, `STANDARD`). `attach_recommended_sequence` reads
|
|
34
|
+
this value + the sender-limits sync (which triggered post-enrich per
|
|
35
|
+
commit `4002b8878`) to pick the template.
|
|
36
|
+
|
|
37
|
+
## Why `attach_recommended_sequence` is load-bearing
|
|
38
|
+
|
|
39
|
+
Without tier-aware routing, the tail would default to a single template
|
|
40
|
+
(historically INVITE → DM) and waste InMail credits on SalesNav senders
|
|
41
|
+
OR try to InMail from a Standard sender (which fails with `not_authorized`
|
|
42
|
+
per Unipile).
|
|
43
|
+
|
|
44
|
+
Commit `14e4cf59a` shipped the tier routing; commit `4002b8878` fixed
|
|
45
|
+
a race where tier limits drifted from actual limits after `enrichProfile`
|
|
46
|
+
writes. Both are required for the matrix to work reliably.
|
|
47
|
+
|
|
48
|
+
## Validation before `attach_recommended_sequence`
|
|
49
|
+
|
|
50
|
+
The tail MUST verify:
|
|
51
|
+
|
|
52
|
+
1. Sender LinkedIn is enriched within the last 24 hours (fresh tier data).
|
|
53
|
+
2. `syncSenderLimits` has been called since the last `enrichProfile`
|
|
54
|
+
write (closes the `4002b8878` race window).
|
|
55
|
+
3. The detected tier maps cleanly to one of the template rows above.
|
|
56
|
+
If tier is `UNKNOWN` or ambiguous, escalate rather than guess.
|
|
57
|
+
|
|
58
|
+
## Hard rules
|
|
59
|
+
|
|
60
|
+
- `attach_recommended_sequence` is the only way to pick a template in
|
|
61
|
+
the autonomous tail. Do NOT hand-wire a sequence at Step 16.
|
|
62
|
+
- Tier mismatch at attach time is an escalation, NOT a silent fallback.
|
|
63
|
+
- A Standard sender MUST NOT be attached to an INMAIL_OPEN template.
|
|
64
|
+
This would produce sends that fail at Unipile with `not_authorized`.
|
|
65
|
+
- An `attach_recommended_sequence` that returns `template: UNKNOWN`
|
|
66
|
+
is an escalation — do not proceed to Step 16 greenlight.
|
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
# Validation Criteria
|
|
2
|
+
|
|
3
|
+
Phase 84 is a chained-artifact validation pass over the Phase 83 brief. The
|
|
4
|
+
goal is to preserve the brief thesis while proving that leads, filters, and
|
|
5
|
+
message direction hold up against real preview evidence.
|
|
6
|
+
|
|
7
|
+
## Primary Contract
|
|
8
|
+
|
|
9
|
+
- `brief.md` is the Phase 83 thesis input
|
|
10
|
+
- `lead-review.md` and `lead-sample.json` are the required outputs of lead preview
|
|
11
|
+
- `lead-filter.md` is the primary output of the middle step
|
|
12
|
+
- `rubric.json` is optional and secondary
|
|
13
|
+
- `message-validation.md` is the final validation output
|
|
14
|
+
|
|
15
|
+
## What Each Step May Change
|
|
16
|
+
|
|
17
|
+
### Find Leads
|
|
18
|
+
|
|
19
|
+
Allowed:
|
|
20
|
+
|
|
21
|
+
- create or replace `lead-review.md`
|
|
22
|
+
- create or replace `lead-sample.json`
|
|
23
|
+
|
|
24
|
+
Not allowed:
|
|
25
|
+
|
|
26
|
+
- rewrite the Phase 83 thesis in `brief.md`
|
|
27
|
+
- create `lead-filter.md`
|
|
28
|
+
- create `message-validation.md`
|
|
29
|
+
- mutate campaign state
|
|
30
|
+
|
|
31
|
+
### Filter Leads
|
|
32
|
+
|
|
33
|
+
Allowed:
|
|
34
|
+
|
|
35
|
+
- create or replace `lead-filter.md`
|
|
36
|
+
- create or replace `rubric.json`
|
|
37
|
+
- append `recent_posts[]` arrays to FIT rows in `lead-sample.json` as
|
|
38
|
+
part of the Post-Filter Signal Enrichment Pass (see `filter-leads.md`
|
|
39
|
+
— top K=10 FIT rows on Sales Nav lane only, via
|
|
40
|
+
`mcp__sellable__fetch_linkedin_posts`)
|
|
41
|
+
|
|
42
|
+
Not allowed:
|
|
43
|
+
|
|
44
|
+
- replace `lead-review.md` or `lead-sample.json` unless a lead revision was requested
|
|
45
|
+
- create approval packet or commit gate before filter completion
|
|
46
|
+
- rely on more than one optional/supporting filter rule
|
|
47
|
+
- call `check_rubric`
|
|
48
|
+
- call `save_rubrics`
|
|
49
|
+
|
|
50
|
+
### Generate Message
|
|
51
|
+
|
|
52
|
+
Allowed:
|
|
53
|
+
|
|
54
|
+
- create or replace `message-validation.md`
|
|
55
|
+
|
|
56
|
+
Not allowed:
|
|
57
|
+
|
|
58
|
+
- run before `lead-review.md` and `lead-sample.json` exist
|
|
59
|
+
- require or infer `campaignId`
|
|
60
|
+
- call `update_cell`
|
|
61
|
+
- call `update_campaign_brief`
|
|
62
|
+
- call `get_rows`
|
|
63
|
+
- call `get_campaign`
|
|
64
|
+
- fetch fresh web or LinkedIn research
|
|
65
|
+
- invent personalization signals that were not validated in `lead-sample.json`
|
|
66
|
+
- widen safe claims beyond `brief.md`
|
|
67
|
+
- leave unresolved `{{token}}`
|
|
68
|
+
- introduce unsupported tokens
|
|
69
|
+
- invent proof, metrics, logos, or customer names
|
|
70
|
+
- skip the dry-mode preamble
|
|
71
|
+
|
|
72
|
+
Required:
|
|
73
|
+
|
|
74
|
+
- **Gold-standard skeleton enforcement.** When the brief's Message
|
|
75
|
+
Thesis says "no greeting / no warm-up", VALIDATE against the
|
|
76
|
+
gold-standard archive (`references/gold-standard-message-examples.md`).
|
|
77
|
+
At least one gold example must exist with that opener style. If NONE
|
|
78
|
+
exists, surface the deviation as a WARNING in `message-validation.md`
|
|
79
|
+
Findings and require explicit operator confirmation before shipping
|
|
80
|
+
the candidate. The default opener is `Hey {{first_name}},` on its own
|
|
81
|
+
line, followed by a blank line and then the first real sentence, unless
|
|
82
|
+
the brief justifies absence with reference to a specific archived winner.
|
|
83
|
+
If a candidate uses `two options:`, option `a)` and option `b)` must be
|
|
84
|
+
separated by a blank line so the CTA scans cleanly on mobile.
|
|
85
|
+
- **All 5 Substance Filters from `thomas-revision-filters.md` MUST
|
|
86
|
+
PASS per candidate.** A candidate that fails any substance filter
|
|
87
|
+
(Earned-right, Presumption, Vague-proof, Read-as-1:1, Founder-origin
|
|
88
|
+
coherence) is BLOCKED. The Finalizer Pass CANNOT select a blocked
|
|
89
|
+
candidate. If all 3 candidates fail, route to `revise-message` with
|
|
90
|
+
the failure reasons enumerated per candidate (cite the filter name and
|
|
91
|
+
the offending line).
|
|
92
|
+
|
|
93
|
+
## Lead Preview Expectations
|
|
94
|
+
|
|
95
|
+
Lead preview must:
|
|
96
|
+
|
|
97
|
+
- use `find-leads` campaignless preview mode
|
|
98
|
+
- avoid `campaignOfferId`
|
|
99
|
+
- avoid `import_leads`
|
|
100
|
+
- avoid `selectedLeadListId`
|
|
101
|
+
- avoid `confirm_lead_list`
|
|
102
|
+
- avoid DB-backed campaign mutation
|
|
103
|
+
|
|
104
|
+
`lead-review.md` must include:
|
|
105
|
+
|
|
106
|
+
- status: `confirmed`, `rejected`, or `unclear`
|
|
107
|
+
- confidence
|
|
108
|
+
- provider path used
|
|
109
|
+
- preview count
|
|
110
|
+
- ICP match rate
|
|
111
|
+
- volume comparison
|
|
112
|
+
- expected LinkedIn funnel: likely connection acceptance range, likely reply
|
|
113
|
+
range, and whether the estimate is sample-backed, historical, founder-supplied,
|
|
114
|
+
or directional
|
|
115
|
+
- source decision: best path, why it won, pros, cons/tradeoffs, and discarded
|
|
116
|
+
source paths with the reason each lost
|
|
117
|
+
- false-positive patterns
|
|
118
|
+
- recommendation for `filter leads` or revision
|
|
119
|
+
|
|
120
|
+
For normal LinkedIn discovery, `lead-review.md` must include literal
|
|
121
|
+
customer-visible headings:
|
|
122
|
+
|
|
123
|
+
- `## Source Decision`
|
|
124
|
+
- `## Expected LinkedIn Funnel`
|
|
125
|
+
- `## Pros`
|
|
126
|
+
- `## Tradeoffs`
|
|
127
|
+
- `## Discarded Paths`
|
|
128
|
+
|
|
129
|
+
`## Expected LinkedIn Funnel` must include expected source volume, expected
|
|
130
|
+
usable leads after filtering, likely connection acceptance range, likely reply
|
|
131
|
+
range, and estimate basis. If exact performance data is unavailable, use a
|
|
132
|
+
directional range and label it `directional`, not definitive.
|
|
133
|
+
|
|
134
|
+
`lead-sample.json` must include enough structured lead data for downstream
|
|
135
|
+
filtering:
|
|
136
|
+
|
|
137
|
+
- person name
|
|
138
|
+
- title
|
|
139
|
+
- company
|
|
140
|
+
- profile URL when available
|
|
141
|
+
- source provider
|
|
142
|
+
- any visible signals used in the review
|
|
143
|
+
|
|
144
|
+
## Filter Leads Expectations
|
|
145
|
+
|
|
146
|
+
Filter leads must treat `lead-filter.md` as the primary artifact.
|
|
147
|
+
|
|
148
|
+
`lead-filter.md` must include:
|
|
149
|
+
|
|
150
|
+
- `Status`
|
|
151
|
+
- `Decision`
|
|
152
|
+
- `Who We'll Keep`
|
|
153
|
+
- `Who We'll Exclude`
|
|
154
|
+
- `Sample False Positives`
|
|
155
|
+
- `Pass Rate`
|
|
156
|
+
- `Recommendation`
|
|
157
|
+
- `Implementation Details`
|
|
158
|
+
|
|
159
|
+
`lead-filter.md` should also include:
|
|
160
|
+
|
|
161
|
+
- one `Optional Supporting Rule` only when it clearly helps downstream
|
|
162
|
+
messaging or prioritization
|
|
163
|
+
- technical `Required Keep Rules` and `Required Exclude Rules` only when needed
|
|
164
|
+
to preserve implementation detail; if present, put them after the
|
|
165
|
+
user-facing sections
|
|
166
|
+
- explicit notes tying repeated false positives from the sample to the final
|
|
167
|
+
exclude rules
|
|
168
|
+
|
|
169
|
+
Filter rules should preserve the recurring campaign families when they are
|
|
170
|
+
relevant to the brief and sample:
|
|
171
|
+
|
|
172
|
+
- buyer role and seniority
|
|
173
|
+
- wrong-function exclusion
|
|
174
|
+
- company-type exclusion
|
|
175
|
+
- competitor/vendor/intermediary exclusion
|
|
176
|
+
- geography
|
|
177
|
+
- company size
|
|
178
|
+
- active current-role status
|
|
179
|
+
|
|
180
|
+
`rubric.json`, when present, must be a translation of the same keep/exclude
|
|
181
|
+
rules and not a second scoring framework:
|
|
182
|
+
|
|
183
|
+
- use the production rubric fields: `checkName`, `description`, `criterion`,
|
|
184
|
+
`reason`, `isRequiredCheck`, `allowPartialCredit`, and `strictMatching`
|
|
185
|
+
- default all rules to `isRequiredCheck: true`
|
|
186
|
+
- allow at most one `isRequiredCheck: false` supporting rule
|
|
187
|
+
- prefer 2-5 total criteria; do not map every bullet to a separate rubric row
|
|
188
|
+
- include the same 2-5 production-shaped criteria in `lead-filter.md` under
|
|
189
|
+
`Implementation Details` as fenced JSON even when `rubric.json` is omitted
|
|
190
|
+
- require `Implementation Details` JSON to parse into an object with
|
|
191
|
+
`leadScoringRubrics`
|
|
192
|
+
- require every criterion to be answerable from row data, enrichment, or public
|
|
193
|
+
research
|
|
194
|
+
- reject duplicate rules that restate the same idea
|
|
195
|
+
- if the sidecar fails to parse, continue with `lead-filter.md` and block only
|
|
196
|
+
downstream sidecar consumers until fixed
|
|
197
|
+
|
|
198
|
+
## Message Validation Expectations
|
|
199
|
+
|
|
200
|
+
Message validation must run in caller-declared `DRY MODE`.
|
|
201
|
+
|
|
202
|
+
Inputs:
|
|
203
|
+
|
|
204
|
+
- `brief.md`
|
|
205
|
+
- `lead-filter.md`
|
|
206
|
+
- `lead-sample.json`
|
|
207
|
+
- `gold-standard-message-examples.md` when `brief.md` lacks a message appendix
|
|
208
|
+
|
|
209
|
+
`message-validation.md` must include:
|
|
210
|
+
|
|
211
|
+
- `Status`
|
|
212
|
+
- `Mode: DRY MODE (no DB mutation)`
|
|
213
|
+
- `Template Used`
|
|
214
|
+
- `Primary Example`
|
|
215
|
+
- `Secondary Influence`
|
|
216
|
+
- `Lead Sample Basis`
|
|
217
|
+
- `Strongest Reply Reason`
|
|
218
|
+
- `Pre-Draft Buyer-Role Analysis`
|
|
219
|
+
- `Campaign Element Pool`
|
|
220
|
+
- `Gold Standard Strategy Map`
|
|
221
|
+
- `Current Campaign Translation`
|
|
222
|
+
- `Element Scoring`
|
|
223
|
+
- `Agent Dialogue Cross-Review`
|
|
224
|
+
- `Proof Inventory`
|
|
225
|
+
- `Token Fill Rules`
|
|
226
|
+
- `Token Adherence Table`
|
|
227
|
+
- `Candidate Messages`
|
|
228
|
+
- `Finalizer Pass`
|
|
229
|
+
- `Selected Winner`
|
|
230
|
+
- `Findings`
|
|
231
|
+
- `Recommendation`
|
|
232
|
+
|
|
233
|
+
The sample set must:
|
|
234
|
+
|
|
235
|
+
- contain 2-3 sample messages
|
|
236
|
+
- use the find-leads message handoff rows or probable good-fit rows from
|
|
237
|
+
`lead-sample.json`; if `lead-filter.md` already exists, use only leads that
|
|
238
|
+
still pass it
|
|
239
|
+
- use only supported tokens documented in the brief
|
|
240
|
+
- contain no unresolved `{{token}}` placeholders
|
|
241
|
+
- resolve every token used in the sample output
|
|
242
|
+
- contain no invented proof, metrics, logos, or customer names
|
|
243
|
+
- keep proof claims inside the brief's safe-claims boundary
|
|
244
|
+
- reject personalization that cannot be traced back to `lead-sample.json`
|
|
245
|
+
- apply Thomas revision filters before the step is marked `confirmed`
|
|
246
|
+
- choose the highest-specificity validated strategy available in this order:
|
|
247
|
+
event-led, signal-led, job-post-led, then proof-led specialist fallback
|
|
248
|
+
- retrieve against the full archived gold-standard library and choose a
|
|
249
|
+
Primary Example plus at most one narrow Secondary Influence
|
|
250
|
+
- run an `Agent Dialogue Cross-Review` before drafts survive: skeptical
|
|
251
|
+
prospect, offer strategist, and gold-standard editor must reconcile to
|
|
252
|
+
approved elements and banned elements before candidate messages are written
|
|
253
|
+
- **treat the archived examples as the quality bar and motion reference,
|
|
254
|
+
not a paste source.** Write fresh sentences from the validated brief that
|
|
255
|
+
could plausibly belong in the archive for this motion
|
|
256
|
+
- exact-template preservation applies **only when the archived winner is the
|
|
257
|
+
same company as the brief**; otherwise match the motion skeleton without
|
|
258
|
+
recoloring the exemplar's wording
|
|
259
|
+
- build a proof inventory before drafting and use at least one compelling proof
|
|
260
|
+
element when the brief supports it
|
|
261
|
+
- document token fill rules before drafting the winner
|
|
262
|
+
- draft 3 candidates, then run a Finalizer Pass that picks the best opener,
|
|
263
|
+
proof sentence, bridge, and CTA across them and assembles the winner
|
|
264
|
+
- the winner entry must name which candidate each borrowed piece came from,
|
|
265
|
+
or declare that one candidate swept the Finalizer Pass (with the winning
|
|
266
|
+
axis named)
|
|
267
|
+
- write at a 5th-grade reading level by default. Jargon is limited to
|
|
268
|
+
brief-native product and tool names (e.g. Shopify, HubSpot, ServiceNow).
|
|
269
|
+
Cut glue language — any B2B compound noun the buyer wouldn't say naturally
|
|
270
|
+
in conversation — even when the brief uses it
|
|
271
|
+
- Casing must look intentional. Lowercase casual style is allowed for common
|
|
272
|
+
words when the chosen motion uses it, but proper nouns, recipient names,
|
|
273
|
+
company names, product names, acronyms, and the pronoun `I` stay capitalized.
|
|
274
|
+
Do not output broken casing like `i'm`, `futureclinic`, or `michael`
|
|
275
|
+
- higher reading levels are only allowed when the archived winner for this
|
|
276
|
+
motion is the **same company as the brief** and uses denser language
|
|
277
|
+
deliberately (e.g. Superposition drafting for Superposition). Lowercase-casual
|
|
278
|
+
motions still read at a plain level and should not be flattened into
|
|
279
|
+
polished prose
|
|
280
|
+
- put a blank line between every sentence in the body, so the body renders
|
|
281
|
+
as a sequence of one-line paragraphs separated by blank lines — not as
|
|
282
|
+
multi-sentence paragraphs. Target 5-8 one-line paragraphs total
|
|
283
|
+
- split sentences that are above ~15 words or carry more than one comma
|
|
284
|
+
- do not stack three workflows into one mechanism line or one comma list.
|
|
285
|
+
Give each workflow its own one-sentence paragraph, or pick the most
|
|
286
|
+
painful one and drop the others
|
|
287
|
+
- **product clarity is non-negotiable**: a cold reader must be able to state
|
|
288
|
+
in one sentence what the product does. Require a crisp `Product is an X
|
|
289
|
+
that does Y` anchor sentence before any action breakdown, then one action
|
|
290
|
+
per one-line paragraph. Do not gesture at "that chain" / "the stack" /
|
|
291
|
+
"that work" in place of naming specific actions
|
|
292
|
+
- body flow must follow: opener → pain → what the product IS (one sentence)
|
|
293
|
+
→ what it DOES (one action per line, up to three) → deployment ease →
|
|
294
|
+
CTA → optional PS
|
|
295
|
+
- the "what it DOES" action list may render as one-line paragraphs or as a
|
|
296
|
+
bullet list — whichever reads cleaner. Bullets are acceptable here (the
|
|
297
|
+
rule against bullet points applies to feature/benefit marketing lists,
|
|
298
|
+
not to enumerable product actions). Never comma-stack three actions into
|
|
299
|
+
one glued sentence
|
|
300
|
+
- **opener must use per-lead signal when any is present in `lead-sample.json`**
|
|
301
|
+
(post, hire, visible tool, topic engagement). Category-level openers are
|
|
302
|
+
acceptable only as fallback when the sample carries zero per-lead signal.
|
|
303
|
+
Fallback category openers must be flagged explicitly in Findings with a
|
|
304
|
+
recommendation to surface signals upstream
|
|
305
|
+
- keep the body tight: one proof sentence, one useful CTA, no vague meeting ask
|
|
306
|
+
- avoid generic walkthrough CTAs like `reply if you want a quick walkthrough`
|
|
307
|
+
unless the line names the useful thing the buyer will see or get
|
|
308
|
+
- the PS is optional. Only include it if it materially strengthens the fit
|
|
309
|
+
case for this buyer. Drop the PS if the best available proof would just
|
|
310
|
+
add noise
|
|
311
|
+
- when a PS is included, it must answer "why is this a fit for me?", not
|
|
312
|
+
"here are our credentials." Never drop a bare first name like "Chris"
|
|
313
|
+
with no anchor. Use "I" voice if the sender is the founder; "our CEO",
|
|
314
|
+
"our team", or "we" otherwise. At most two proof beats. No three-credential
|
|
315
|
+
resume lists
|
|
316
|
+
- samples in one set must read like siblings from one campaign, not three
|
|
317
|
+
experiments
|
|
318
|
+
- reject fallback drafts that lead with generic "most teams..." copy without a
|
|
319
|
+
concrete workflow anchor
|
|
320
|
+
- reject fallback drafts that open with synthesized "X means you're likely..."
|
|
321
|
+
or "at your stage" framing
|
|
322
|
+
- reject drafts that default to a lead magnet, report, brief, teardown,
|
|
323
|
+
video, or "send it over" CTA when the brief never said that asset exists
|
|
324
|
+
- reject drafts that use a `PS` above the CTA or in the middle of the body
|
|
325
|
+
- reject drafts that omit stronger safe proof already present in the brief
|
|
326
|
+
- avoid em dashes unless the chosen Primary Example uses them
|
|
327
|
+
|
|
328
|
+
When message validation fails because sourcing is weak:
|
|
329
|
+
|
|
330
|
+
- revise token fill rules
|
|
331
|
+
- or revise the filter
|
|
332
|
+
- or revise the message thesis
|
|
333
|
+
|
|
334
|
+
Do not invent a stronger signal just to save the copy.
|
|
335
|
+
|
|
336
|
+
`Template Used` must name the actual strategy being validated, not just a vague
|
|
337
|
+
theme:
|
|
338
|
+
|
|
339
|
+
- `event-led canonical template`
|
|
340
|
+
- `signal-led canonical template`
|
|
341
|
+
- `job-post-led canonical template`
|
|
342
|
+
- `proof-led specialist fallback`
|
|
343
|
+
|
|
344
|
+
If `brief.md` includes a message appendix, worked example, or interpolation
|
|
345
|
+
guidance, the sample messages should follow that structure closely. Otherwise,
|
|
346
|
+
the system should synthesize the structure from the closest archived winner.
|
|
347
|
+
Proof-led specialist fallback is only acceptable when no stronger validated
|
|
348
|
+
hook exists.
|
|
349
|
+
|
|
350
|
+
`Primary Example` should name the archived winner providing the structure.
|
|
351
|
+
`Secondary Influence` should be `none` or name one narrow influence only.
|
|
352
|
+
|
|
353
|
+
## Stop Conditions
|
|
354
|
+
|
|
355
|
+
- `brief.md` missing
|
|
356
|
+
- provider/auth/quota error during preview
|
|
357
|
+
- zero usable leads from preview
|
|
358
|
+
- sample too small to judge
|
|
359
|
+
- required upstream artifact missing for the next step
|
|
360
|
+
- `lead-filter.md` missing required keep/exclude sections
|
|
361
|
+
- more than one optional/supporting rule proposed
|
|
362
|
+
- `message-validation.md` missing the dry-mode preamble
|
|
363
|
+
- any sample message contains unresolved or unsupported tokens
|
|
364
|
+
- any sample message contains invented proof or unsupported personalization
|
|
365
|
+
|
|
366
|
+
When a stop condition is hit, surface the reason in the relevant artifact and
|
|
367
|
+
do not attempt to mint live campaign state.
|