@sellable/mcp 0.1.37 → 0.1.38-rc.2

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.
@@ -761,1265 +761,28 @@ Do not:
761
761
 
762
762
  ## Step 3: Generate Message
763
763
 
764
- Read `brief.md`, `lead-review.md`, `lead-sample.json`, optional
765
- `lead-filter.md`, optional `message-prep.md`, and optional
766
- `message-candidate-drafts.md`.
764
+ The full Step 3 detail (~45k chars: message-validation workflow, gold-standard rules, proof inventory, candidate generation, finalizer pass, message-review-decision contract, A+B+C subject shape, token-fill rules, etc.) lives in a dedicated on-demand subskill to keep this entry prompt fast to load.
767
765
 
768
- This branch can run in parallel with Step 2 once `lead-review.md` and
769
- `lead-sample.json` exist. If `lead-filter.md` is not ready yet, draft from the
770
- lead-review message handoff rows, then reconcile after the filter lands.
766
+ When you reach Step 3, **load the dedicated subskill verbatim**:
771
767
 
772
- Write:
768
+ ```
769
+ mcp__sellable__get_subskill_prompt({ subskillName: "create-campaign-v2-generate-message" })
770
+ ```
773
771
 
774
- - `message-validation.md`
775
-
776
- Run the `generate-messages` skill in caller-declared `DRY MODE`. Its SKILL.md
777
- holds the full drafting contract (retrieval, proof inventory, candidates,
778
- finalizer pass, voice rules, safety). This step only covers orchestration.
779
- This is not optional: before any write to `message-validation.md`,
780
- `message-review.md`, `approval-packet.md`, or a commit-gate question, the
781
- current run must load the full `generate-messages` prompt. In hosted/from-
782
- scratch runs, load it with chunked `get_subskill_prompt({ subskillName:
783
- "generate-messages", offset, limit })` calls so every tool result stays small
784
- enough for the streamed harness. Start with `offset: 0`; the MCP will apply a
785
- portable default limit when omitted. Keep calling with `offset: nextOffset`
786
- until `hasMore` is false.
787
- In Codex-hosted runs, this is a quality gate, not just provenance: if the
788
- model cannot retrieve the complete prompt or cannot follow the required
789
- gold-standard deliberation flow, stop at `message-review` and ask for
790
- `revise-messaging`. Do not mint the campaign to compensate for weak copy.
791
- Do not hand-write `message-validation.md` from `message-prep.md` or
792
- `message-candidate-drafts.md`. Those files are planning inputs only; the final
793
- message-validation artifact must come from the actual `generate-messages`
794
- prompt path (`get_message_prompt` / `generate-messages`).
795
-
796
- Orchestration requirements:
797
-
798
- - start once real leads exist: `brief.md`, `lead-review.md`, and
799
- `lead-sample.json` are enough to run generate-message
800
- - use only the find-leads message handoff rows as basis examples, e.g.
801
- "prospects 1, 5, and 6 are solid enough to think from"
802
- - if `lead-filter.md` is ready, use it; if it arrives after message drafting,
803
- reconcile before approval and rerun or revise messaging if the selected
804
- winner depended on rows that fail the final filter
805
- - never write `message-validation.md`, render a message review, render an
806
- approval packet, or ask the commit gate until 100% of the real
807
- `generate-messages` prompt has been read
808
- - before `message-review` can recommend `approve-message`, verify
809
- `message-validation.md` contains the full generate-messages shape:
810
- `Gold Standard Strategy Map`, `Proof Inventory`, `Token Fill Rules`,
811
- `Token Adherence Table`, `Angle Drafts`, `Kill / Combine Review`,
812
- `Finalists`, `Finalizer Pass`, `Gold-Standard Quality Gate`,
813
- `Skeptical Prospect Review`, `Winner Gate`, and a raw sendable
814
- `Selected Winner`. If any are missing, recommend `revise-messaging` and do
815
- not continue to approval or mint.
816
- - pass no `campaignId`
817
- - read only `brief.md`, `lead-review.md`, `lead-sample.json`, optional
818
- `lead-filter.md`, and the `gold-standard-*` references. If
819
- `message-prep.md` exists, use it as a
820
- planning cache instead of redoing the same element inventory from scratch. If
821
- `message-candidate-drafts.md` exists, use it as provisional draft input only
822
- after checking its basis rows against the completed `lead-filter.md`, when
823
- available.
824
- - generate 2-3 sample messages inline
825
- - start output with `Mode: DRY MODE (no DB mutation)`
826
- - treat the archived examples as the **quality bar**, not a paste source;
827
- write messages that could plausibly belong in the archive for this motion
828
- - exact-template preservation only applies when the archived winner is the
829
- same company as the brief
830
- - draft 3 internal candidates and run a Finalizer Pass that combines the
831
- best opener, proof sentence, bridge, and CTA across them into one winner
832
- - if all finalists use the same first substantive line, treat the opener
833
- test as failed; compare materially different opener jobs before selecting
834
- a winner, or route to `revise-message`
835
- - the Finalizer Pass must block adjacent repeated copy. Do not let a pain
836
- line and mechanism line reuse the same noun stack unless the second line
837
- adds plainly new buyer value. Merge, translate, bullet, or cut instead.
838
- - the selected winner subject/body must not contain semicolons.
839
- - the selected winner subject must not be generic category copy like
840
- `first LinkedIn campaign`, `quick question`, `outbound`, or `intro`. Prefer the
841
- original gold-standard A + B + C subject shape: a concrete row/company token
842
- plus a concrete workflow/object plus the offer/result, for example
843
- `{{company}} + LinkedIn outbound + Claude/Codex` or
844
- `{{source_post_topic}} + active leads + first message test`. Keep it short,
845
- buyer-native, and free of abstract category nouns.
846
- - A + B + C is a quality shape, not permission to stuff tokens into the
847
- subject. The subject must pique buyer interest and name a buyer-relevant
848
- problem, workflow, or useful artifact. Do not use sender names, founder names,
849
- "Austin's review", "founder call", "demo", "quick call", or similar
850
- sender-centered language in the subject. Do not use a row token in the subject
851
- unless the filled version is natural, lowercase/common-word where appropriate,
852
- and more interesting than the non-tokenized version.
853
- - the selected winner must not contain sender-intro fragments like
854
- `Usama here`, `derm here`, `board-cert derm here`, `[credential] here`,
855
- or `[role] at [company] here`.
856
- - the selected winner must not use generic signal tokens such as
857
- `{{recentSignal}}`, `{{recent_signal}}`, or `{{recent_signal_quote}}`.
858
- Row personalization must use concrete enriched-row fields such as
859
- `{{post_context}}`, `{{comment_summary}}`, `{{profile_summary}}`,
860
- `{{source_post_topic}}`, `{{headline}}`, or `{{row_proof_note}}`, and it
861
- must avoid source-citation phrases like `caught my eye`.
862
- - do not default to founder-to-founder, MD-to-MD, doctor-to-doctor,
863
- peer-call, compare-notes, or similar identity-call CTA framing unless
864
- the user explicitly selected that route or the brief makes it the
865
- approved offer. Even then, the CTA must name the useful return artifact,
866
- preview, teardown, or working session.
867
- - if the message is selling or introducing a product, the selected winner
868
- must make the product plain before asking for time, but the opener must
869
- not sound like homepage copy. A line shaped like `[Product] is a
870
- [category] platform -- feature, feature, feature` is blocked when it reads
871
- like product copy instead of a human note. For command-native products,
872
- describe the buyer job (`launch a LinkedIn campaign from Claude/Codex`)
873
- before category nouns like `platform` or `MCP`.
874
- - pass the Thomas revision filters before writing findings
875
- - immediately after `message-validation.md` is confirmed and reconciled with
876
- `lead-filter.md`, write `message-review.md` and render the slim chat version
877
- inline starting with `Status: message-review` as the first visible line. Do
878
- not put a markdown heading, preface, or summary before that status line.
879
- This is a customer checkpoint optimized for fast approve / revise judgment.
880
- - Chat-vs-file split (this is the rule the user pinned):
881
- - `message-review.md` (the file) keeps the full detail: `Status:
882
- message-review`, `Subject:`, `Tokenized template:`, `Sample prospect fill:` + `Token fill basis:`, `Rendered examples:`, `Good token fill:`,
883
- `Good omit:`, `Bad token fill:`, `Why bad:`, `Fallback if missing:`,
884
- `Token notes:`, `My take:`, `Suggested adjustment:`, `Question:
885
- approve-message or revise-messaging?`, `Recommendation:
886
- approve-message|revise-messaging`. The detailed gold-standard/rule audit
887
- stays in `message-validation.md`. Both files are unchanged in scope and
888
- are still required.
889
- - The chat rendering shows ONLY: `Status: message-review`, `Subject:`,
890
- `Tokenized template:`, `Sample prospect fill:` (with `Token fill basis:`),
891
- `My take:`, `Suggested adjustment:`, `Question: approve-message or
892
- revise-messaging?`, `Recommendation:`. Then `Open artifacts:` links to
893
- `message-review.md` and `message-validation.md` so the user can read the
894
- full token guidance, good/omit/bad examples, and fallbacks if they want
895
- to before deciding.
896
- - Do NOT inline `Rendered examples:`, `Good token fill:`, `Good omit:`,
897
- `Bad token fill:`, `Why bad:`, `Fallback if missing:`, or `Token notes:`
898
- in chat. Those exist in the file and are linked. Keeping them out of
899
- chat is what makes the gate easy to approve or revise on.
900
- - Never ask the message approval question until the slim chat review is fully
901
- visible. A summary like `Message review is ready` or `the draft avoids a
902
- generic pitch` is not enough. The user must see the actual subject, the
903
- actual tokenized message template, one filled sample prospect version with
904
- its token fill basis, your take, and the suggested adjustment before any
905
- `approve-message` / `revise-messaging` question appears. If you catch
906
- yourself wanting to offer `show me message` as a choice, stop: render the
907
- slim chat review first, then ask only `approve-message` or
908
- `revise-messaging`. Include `Open artifacts:` links to `message-review.md`
909
- and `message-validation.md` before the approval question.
910
- - `My take:` and `Suggested adjustment:` are mandatory customer-facing decision
911
- fields, not optional summary text. They must appear after `Token notes:` and
912
- before the question in every rendered message review. They must each be
913
- non-empty, specific to the current message, and useful for one last manual
914
- feedback pass. Never render a message review that jumps straight from token
915
- notes to `Question:` or `Recommendation:`.
916
- - `Tokenized template:` in `message-review.md` must be a tokenized template with supported
917
- enriched-row tokens such as `{{first_name}}`, `{{company}}`,
918
- `{{workflow_context}}`, `{{headline}}`, `{{source_post_topic}}`, or
919
- `{{row_proof_note}}`. It must not be a one-row-only raw sample. It must
920
- include at least one literal `{{...}}` token. Keep only tokens that future
921
- enriched rows can actually fill or safely omit. If you cannot produce a
922
- tokenized template from supported enriched-row fields, stop with
923
- `Recommendation: revise-messaging`.
924
- - `Sample prospect fill:` must render the same template for one named sample
925
- prospect from `lead-sample.json` or the selected row used in
926
- `message-validation.md`. It must show the complete subject and body the
927
- prospect would receive, plus a one-line `Token fill basis:` naming which row
928
- fields filled each token. This is the user-facing proof that the template
929
- works. Do not ask for approval if the user cannot compare the template to a
930
- concrete filled message.
931
- - `{{profile_signal}}` is never a supported customer-facing token. It is an
932
- internal enrichment label and must not appear in `Subject:`, `Tokenized
933
- template:`, `Sample prospect fill:`, rendered examples, `Token notes:`,
934
- `message-validation.md` selected copy, or `approval-packet.md`. If a
935
- profile-derived signal matters, translate it into a buyer-readable derived
936
- token with a clear fill rule, such as `{{workflow_context}}` or
937
- `{{row_proof_note}}`; otherwise omit the line.
938
- - `Rendered examples:` must include at least one `Good token fill:` rendered
939
- message where the row has a clean signal and one `Good omit:` rendered message
940
- where an optional token line is omitted instead of forced. Each example must
941
- be a complete rendered subject + body, not a bullet list of token names or a
942
- single bridge-line fragment. Do not use bracketed instructions, deferred row
943
- notes, or phrases like `approve the selected winner above`.
944
- - `Bad token fill:` must show at least one realistic wrong fill for the current
945
- campaign, followed by `Why bad:`. This teaches the user and the live campaign
946
- runtime what not to do. Examples: overclaiming signal intent (`you are
947
- evaluating Clay` when the only evidence is a post reaction), using forbidden
948
- phrasing (`you engaged with content...` when the approved voice is `raised
949
- your hand in a conversation around...`), forcing a weak optional token,
950
- lowercasing proper nouns, or making row signal sound like AI mail merge.
951
- - `Fallback if missing:` is required for every token in the template. Each
952
- fallback must say exactly what to do when the row lacks clean data: use a
953
- safe segment-level phrase, omit the sentence/line, or route to
954
- `revise-messaging` if omission would break the message. It must include a
955
- concrete example of the fallback behavior, such as `omit the noticed... line`,
956
- `use "operators"`, or `use "your outbound workflow"`. Never leave a token
957
- with "N/A", "unknown", empty braces, bracketed instructions, or a generic
958
- fill that sounds robotic or creepy.
959
- - rendered examples may only use token values that exist in `lead-sample.json`,
960
- `lead-review.md`, `lead-filter.md`, or the selected winner's documented
961
- supported-token plan. Do not invent example values to make the template look
962
- better. If a token is absent, weak, or not a supported enriched-row field,
963
- show the `Good omit:` version instead of filling it.
964
- - token casing must look intentional. Keep proper nouns, recipient names,
965
- company names, product names, acronyms, and the pronoun `I` capitalized in
966
- both the template examples and rendered output. Casual lowercase is allowed
967
- only for static common words when the chosen message voice uses it. Do not
968
- lowercase token values or invent transform syntax like `{{company_lower}}`,
969
- `{{first_name | lower}}`, or bracketed casing instructions.
970
- - Token usage must be intelligent, not decorative. If a tokenized opener reads
971
- like mail merge (`Reaching out because {{reporting_context}} sits in...`,
972
- `your {{role_context}} work`, `saw your {{topic}}`, or similar), rewrite the
973
- base line so the token either sounds like a natural noun phrase or is omitted.
974
- Prefer row-derived tokens that change the reply reason; otherwise use a clean
975
- segment-level line and document why the row token is omitted.
976
- - founder/sender names should not be used as the hook. Mention a founder name
977
- only when the buyer already has a reason to care about that person or when the
978
- user explicitly wants named-founder branding. In normal first-touch copy,
979
- frame the CTA around the useful return artifact (`map one reporting problem`,
980
- `review one dashboard`, `pressure-test one workflow`) instead of "call with
981
- Austin" or another founder-name CTA.
982
- - message-review hard-fail preflight: before rendering `Status: message-review`,
983
- scan the subject, tokenized template, good-fill example, good-omit example,
984
- `My take`, `Suggested adjustment`, and recommendation. If any of them contain
985
- `felt close enough to send`, `close enough to send`,
986
- `thought this was relevant enough`, `seemed close
987
- enough`, `{{profile_signal}}`, `profile signal`, `is why I thought this might
988
- be relevant`, `Austin's`, a sender/founder name in the subject, a one-row raw
989
- sample under `Tokenized template:`, rendered examples without full copy, a
990
- mail-merge-sounding tokenized opener, missing or empty `My take:`, missing or
991
- empty `Suggested adjustment:`, `My take:` that only says `looks good`,
992
- `strong`, or `approved`, `Suggested adjustment:` that only says `none`, or no
993
- literal `{{...}}` token in `Tokenized template:`, revise the message before
994
- showing it. Do not output
995
- `Recommendation: approve-message` when any hard-fail preflight item is
996
- present.
997
- - `My take` must be 1-3 short bullets or sentences, focused on what a founder
998
- needs to decide: approve as-is, revise once, make it shorter, make it more
999
- specific, change proof, change CTA, or preserve the current length because
1000
- cutting would remove reply reason. If a shorter version is recommended,
1001
- `Suggested adjustment` must say exactly what to remove or compress. Do not
1002
- include a long `What works`, `Gold-standard/rule check`, or internal checklist
1003
- in this checkpoint.
1004
- - `Suggested adjustment` must give the founder a concrete final-edit option even
1005
- when the recommendation is `approve-message`. Use a useful shape like
1006
- `Approve as-is, or revise once to [specific edit] if you want [effect]`. It
1007
- must invite the user to give manual feedback before minting, for example:
1008
- `Reply revise-messaging with the exact line change, proof change, CTA change,
1009
- or tone feedback you want before I build the approval packet.` Do not write
1010
- `none`.
1011
- - if the message is merely plausible, generic, template-shaped, or weaker than
1012
- the loaded gold-standard examples, set `Recommendation: revise-messaging`.
1013
- The next Codex UAT goal is to prove message quality before mint, so no
1014
- approval packet or campaign mutation should happen just because the mechanics
1015
- are working.
1016
- - immediately after rendering `message-review.md`, use the structured question
1017
- gate with exactly two choices, in this order: `approve-message`,
1018
- `revise-messaging`. Stop after the question. Do not write `approval-packet.md`,
1019
- `customer-roleplay.md`, or a commit-gate question until
1020
- `message-review-decision.md` contains `approve-message`.
1021
- - if the selected winner or PS uses named customer/logo proof, quantified proof,
1022
- team credentials, or investor/accelerator proof that is not explicitly
1023
- supported by `brief.md`, `lead-review.md`, `lead-sample.json`, or loaded
1024
- reference material, the review must set `Recommendation: revise-messaging`.
1025
- Do not approve speculative credibility claims.
1026
- - if the selected winner or PS uses vague proof wrappers like `spoken publicly
1027
- about`, `publicly talked about`, `trusted by`, `worked with`, `used by`, or
1028
- bare customer-logo lists without naming a concrete buyer-relevant result,
1029
- mechanism, or risk reducer, the review must set `Recommendation:
1030
- revise-messaging`. Supported logos are not automatically body-worthy proof.
1031
- Translate to a concrete proof line or omit the proof from the message.
1032
- - if customer/logo proof is useful mainly for credibility, prefer a concise PS
1033
- over interrupting the body. The PS must name what the customers used the
1034
- product/service for, not just list logos. If the body already carries buyer
1035
- pain, mechanism, and CTA clearly, adding concrete social proof in the PS is
1036
- allowed when it lowers vendor risk.
1037
- - the selected winner or PS must not use internal labels like `p.s. relevant
1038
- proof:`, `p.s. useful proof:`, `p.s. proof:`, or `p.s. social proof:`.
1039
- Rewrite as a natural aside before asking the user to approve.
1040
- - if the user chooses `revise-messaging`, write `message-review-decision.md`
1041
- with `revise-messaging`, preserve upstream artifacts, delete/regenerate
1042
- only `message-validation.md`, `message-review.md`,
1043
- `message-review-decision.md`, `customer-roleplay.md`, and
1044
- `approval-packet.md`, then rerun this message step.
1045
- - after `message-review-decision.md` contains `approve-message`, write
1046
- `approval-packet.md` in customer-facing order and render the same approval
1047
- packet inline before the commit gate. The approval packet and six-choice
1048
- commit question must appear in the same customer-visible turn. Do not emit a
1049
- standalone commit-gate question. Include a clear `## Message Review` section
1050
- inside the approval packet before `## Approved Message Template`. It should
1051
- summarize the customer checkpoint from `message-review.md` and preserve the
1052
- same literal `My take:`, `Suggested adjustment:`, `Good token fill:`,
1053
- `Good omit:`, `Bad token fill:`, `Why bad:`, `Fallback if missing:`,
1054
- `Token fill basis:`, and `Recommendation:` labels.
1055
- Include `Open artifacts:` links to `approval-packet.md`,
1056
- `message-review.md`, `lead-review.md`, and `brief.md` before the commit-gate
1057
- question.
1058
- - if `message-validation.md` contains an extractable `Selected Winner`, use
1059
- that exact winner as the `## Approved Message Template` in
1060
- `approval-packet.md` and in the campaign brief passed to `create_campaign`.
1061
- Only substitute concrete enriched-prospect-row `{{tokens}}`; do not rewrite
1062
- the copy inline at approval time. Do not use abstract slot tokens like
1063
- `{{hookLine}}`, `{{painLine}}`, `{{productLine}}`, `{{closeLine}}`, or
1064
- `{{psLine}}`, and do not use `{{recent_signal_quote}}`; use fields that exist
1065
- on the enriched prospect row instead.
1066
- - the live body under `## Approved Message Template` must be sender-ready copy.
1067
- Bracketed text in the body is allowed only when it is a fully-specified
1068
- AI-native token (`[ALL_CAPS_NAME — Intent. DO: ... DON'T: ... FALLBACK:
1069
- omit the line.]` — see
1070
- `mcp/sellable/skills/create-campaign/references/ai-native-tokens.md` for the
1071
- contract). Bracketed instruction placeholders that lack a contract are
1072
- BLOCKED — including `[ROW BRIDGE ...]`, `[insert ...]`, `[generated ...]`,
1073
- and any prose that defers per-row composition to a later step without
1074
- giving the model the rules. Either upgrade the placeholder to a full
1075
- AI-native token (Intent / DO / DON'T / FALLBACK), put the per-row rules in
1076
- `## Token Fill Rules` with concrete enriched-row fields, or route to
1077
- `revise-messaging`.
1078
- - `approval-packet.md` and the live campaign brief passed to `create_campaign`
1079
- must include `## Approved Message Template`, `## Token Fill Rules`, and
1080
- `## Token Fill Examples`. `## Token Fill Examples` must copy the approved
1081
- examples from `message-review.md` / `message-validation.md`, including
1082
- `Good token fill:`, `Good omit:`, `Bad token fill:`, `Why bad:`,
1083
- `Fallback if missing:`, and `Token fill basis:`. Do not call
1084
- `create_campaign` if these sections are missing from the campaign brief.
1085
- - `message-validation.md` must not call the winner a canonical template or
1086
- hide per-row generation in bracketed body text. `## Selected Winner` must
1087
- be a real sendable message that could be approved as-is.
1088
- - block awkward bridge phrasing like `felt close enough to send this`,
1089
- `thought this was relevant enough`, or `seemed close enough`. Replace with a
1090
- crisp row-backed bridge using a buyer-readable row-derived token, such as
1091
- `That {{workflow_context}} work is where teams usually need cleaner reporting
1092
- ownership.` If the signal is weak or absent, omit the bridge line entirely.
1093
- - if subject, tokenized template, or rendered examples do not meet the bar,
1094
- `message-review.md` must recommend `revise-messaging`, not `approve-message`.
772
+ Follow that prompt verbatim. It contains the full message-validation workflow, gold-standard rules, proof inventory, candidate generation, finalizer pass, message-review-decision contract, and all token-fill rules (A+B+C subject shape, Good/Bad token-fill examples, fallback-if-missing logic, tokenized templates).
1095
773
 
1096
- Do not:
774
+ Do NOT proceed to Step 4 (message review gate) without loading and following the generate-message subskill — message-validation.md must prove the full generate-messages workflow ran, and that workflow is defined in the subskill.
1097
775
 
1098
- - call `get_campaign`
1099
- - call `get_rows`
1100
- - call `update_cell`
1101
- - call `update_campaign_brief`
1102
- - fetch fresh web or LinkedIn research
1103
- - mutate DB-backed campaign state
776
+ ## Tail (MANDATORY TOOL ORDER + Steps 13-16 + Threshold Trips + Hard Rules)
1104
777
 
1105
- `message-validation.md` must contain:
1106
-
1107
- - `Status`
1108
- - `Mode`
1109
- - `Template Used`
1110
- - `Primary Example`
1111
- - `Secondary Influence`
1112
- - `Lead Sample Basis`
1113
- - `Strongest Reply Reason`
1114
- - `Pre-Draft Buyer-Role Analysis`
1115
- - `Campaign Element Pool`
1116
- - `Gold Standard Strategy Map`
1117
- - `Current Campaign Translation`
1118
- - `Element Scoring`
1119
- - `Proof Inventory`
1120
- - `Token Fill Rules`
1121
- - `Token Adherence Table`
1122
- - `Angle Drafts`
1123
- - `Kill / Combine Review`
1124
- - `Finalists`
1125
- - `Candidate Messages`
1126
- - `Finalizer Pass`
1127
- - `Gold-Standard Quality Gate`
1128
- - `Skeptical Prospect Review`
1129
- - `Winner Gate`
1130
- - `Selected Winner`
1131
- - `Findings`
1132
- - `Recommendation`
778
+ The full tail detail (~17k chars: MANDATORY TOOL ORDER, auto-execute-leads, validate-sample loop, auto-execute-messaging, awaiting-user-greenlight, threshold-trip logging, tail hard rules) lives in a dedicated on-demand subskill to keep this entry prompt fast to load.
1133
779
 
1134
- `approval-packet.md` must contain:
1135
-
1136
- - campaign direction
1137
- - lead source and sample
1138
- - filters and rubrics
1139
- - selected message(s)
1140
- - `## Message Review` with literal `My take:`, `Suggested adjustment:`, and
1141
- `Recommendation:` (`approve-message` or `revise-messaging`). If the message
1142
- is only okay, say so plainly so the user can choose `revise-messaging` at the
1143
- commit gate.
1144
- - `## Approved Message Template`; when `message-validation.md` has a selected
1145
- winner, this section must preserve that selected winner rather than a newly
1146
- drafted approval-template variant
1147
- - risks / caveats
1148
- - next action: the six-choice commit gate
1149
-
1150
- `message-review.md` must contain:
1151
-
1152
- - `Status: message-review`
1153
- - `Subject:` using the approved tokenized A + B + C subject shape
1154
- - `Tokenized template:` followed by the tokenized approved message template
1155
- - `Sample prospect fill:` with one concrete sample prospect's complete rendered
1156
- subject + body and a `Token fill basis:` line
1157
- - `Rendered examples:`
1158
- - `Good token fill:` with a complete concrete rendered subject + body
1159
- - `Good omit:` with a complete concrete rendered subject + body where optional
1160
- row signal is omitted cleanly
1161
- - `Bad token fill:` with a realistic wrong fill for the current campaign
1162
- - `Why bad:` explaining the exact overclaim, unsupported token, weak signal,
1163
- casing mistake, or mail-merge phrasing that makes the bad fill unacceptable
1164
- - `Fallback if missing:` with one concrete fallback or omit example for every
1165
- token in the template
1166
- - `Token notes:` naming which tokens are safe to fill, which optional token line
1167
- should be omitted when absent, and whether the message uses standard sentence
1168
- case or casual lowercase static words
1169
- - `My take:`
1170
- - `Suggested adjustment:` with a concrete final-edit option and explicit
1171
- invitation to give manual feedback before approval
1172
- - `Question: approve-message or revise-messaging?`
1173
- - `Recommendation:` exactly `approve-message` or `revise-messaging`
1174
- - The two-choice structured question gate immediately after the rendered review
1175
-
1176
- `message-review-decision.md` must contain exactly one selected route:
1177
- `approve-message` or `revise-messaging`. It does not authorize DB mutation.
1178
-
1179
- If token sourcing is weak, revise token fill rules or route back to
1180
- `revise-filter` or `revise-message` instead of guessing.
1181
-
1182
- </step_contracts>
1183
-
1184
- <resume_rules>
1185
-
1186
- Phase 84 validation resume:
1187
-
1188
- - No `brief-v1.md` / `brief.md` present -> run `create-campaign-brief`
1189
- - `brief-v1.md` present but no `brief.md` -> copy `brief-v1.md` to `brief.md`,
1190
- then run `find leads`
1191
- - Only `brief.md` present -> compatibility resume: run `find leads`
1192
- - `lead-review.md` + `lead-sample.json` present, but no `lead-filter.md` and
1193
- no `message-validation.md` -> run `filter leads` and `generate message`
1194
- from the same find-leads basis; do not ask the user between them when
1195
- lead-review is confirmed
1196
- - `lead-review.md` + `lead-sample.json` present, but no `lead-filter.md` -> run
1197
- `filter leads`
1198
- - `lead-review.md` + `lead-sample.json` present, but no
1199
- `message-validation.md` -> run `generate message`
1200
- - `lead-filter.md` + `message-validation.md` present -> reconcile message
1201
- basis rows against the final filter, then write/render `message-review.md`
1202
- and ask the two-choice message review gate
1203
- - `message-validation.md` present but no `message-review-decision.md` -> write
1204
- `message-review.md`, render it inline starting with `Status:
1205
- message-review`, then ask `approve-message` vs `revise-messaging`
1206
- - `message-review-decision.md` contains `revise-messaging` -> preserve
1207
- upstream artifacts; delete only `message-validation.md`,
1208
- `message-review.md`, `message-review-decision.md`,
1209
- `customer-roleplay.md`, and `approval-packet.md`; rerun `generate message`
1210
- - `message-review-decision.md` contains `approve-message` but no
1211
- `approval-packet.md` -> write `approval-packet.md`, render that packet inline
1212
- starting with `Status: approval-packet`, then ask the six-choice commit gate
1213
- in the same turn
1214
- - `message-validation.md` + `message-review-decision.md` +
1215
- `approval-packet.md` present -> validation complete,
1216
- render `approval-packet.md` inline starting with `Status: approval-packet`,
1217
- then ask the six-choice commit gate in the same turn
1218
- - `lead-review.md` without `lead-sample.json`, or vice versa -> stop with a
1219
- contract violation
1220
- - `lead-filter.md` without upstream lead artifacts -> stop with a contract violation
1221
-
1222
- Phase 85 commit-gate + atomic-mint resume:
1223
-
1224
- - All validation artifacts present and `message-review-decision.md` contains
1225
- `approve-message` but no `approval-packet.md` yet -> write the approval
1226
- packet, render it inline, then show the commit gate in the same turn (see
1227
- `<commit_gate>` below)
1228
- - `approval-packet.md` present but no `commit-gate-decision.md` -> show the
1229
- approval packet inline and then the commit gate in the same turn; an existing
1230
- positive `customer-roleplay.md` is advisory only
1231
- - `commit-gate-decision.md` is a revision choice or `abort` -> route without
1232
- DB mutation
1233
- - `commit-gate-decision.md` contains `approve` and no `CampaignOffer` minted
1234
- yet -> run atomic mint
1235
- - `CampaignOffer` exists and `currentStep = "auto-execute-leads"` -> resume
1236
- via `create_campaign({ campaignId })` to re-fetch state + `watchUrl`,
1237
- re-surface the watch link using `references/watch-link-handoff.md`, and
1238
- continue into the autonomous tail at Step 13
1239
-
1240
- Phase 85 autonomous-tail resume (Plan 85-02):
1241
-
1242
- - `CampaignOffer.currentStep === "auto-execute-leads"` -> run Step 13
1243
- (import) then advance to `validate-sample`
1244
- - `CampaignOffer.currentStep === "validate-sample"` -> run Step 14 sample
1245
- validation loop. Read the persisted `revisionRound` counter and do NOT
1246
- reset it to 0 on resume
1247
- - `CampaignOffer.currentStep === "auto-execute-messaging"` -> run Step 15
1248
- messaging scale-up
1249
- - `CampaignOffer.currentStep === "awaiting-user-greenlight"` -> Step 16:
1250
- re-surface `watchUrl` + `handoff.orientation` and STOP. Do not call
1251
- `start_campaign` on resume. Wait for UI start or a Claude greenlight
1252
- turn
1253
- - `CampaignOffer.currentStep === "running"` -> campaign is live. Surface
1254
- a "campaign is live" confirmation + `watchUrl`. Do not re-start
1255
-
1256
- On every tail resume, re-surface the `watchUrl` and the current step's
1257
- orientation string (v1 create-campaign watch-mode pattern). Load the
1258
- relevant reference for the active step:
1259
-
1260
- - Step 14 -> `references/sample-validation-loop.md`
1261
- - any escalation path -> `references/escalation-ladder.md`
1262
- - Step 16 -> `references/final-handoff-contract.md`
1263
-
1264
- </resume_rules>
1265
-
1266
- <commit_gate>
1267
-
1268
- After Phase 84 artifacts are complete, show the user a commit gate before any
1269
- DB mutation. Load `references/approval-gate-framing.md` for the full
1270
- framing — especially the approval packet ordering and per-choice draft
1271
- directory effects.
1272
-
1273
- Preconditions (block the gate when missing):
1274
-
1275
- - `brief-v1.md` should exist for from-scratch runs
1276
- - `brief.md` must exist
1277
- - `lead-review.md` must exist
1278
- - `lead-sample.json` must exist
1279
- - `lead-filter.md` must exist
1280
- - `message-validation.md` must exist
1281
- - `message-review.md` must exist
1282
- - `message-review-decision.md` must exist and contain `approve-message`
1283
- - `approval-packet.md` must be written before asking for a commit decision
1284
- - `rubric.json` is optional but strongly preferred
1285
-
1286
- Anchor validation (block `approve` when empty):
1287
-
1288
- - `brief.md` has a non-empty `## Message Thesis`
1289
- - `lead-review.md` status is `confirmed`
1290
- - `lead-sample.json` parses and contains at least one row
1291
- - `lead-filter.md` has `Decision`, `Who We'll Keep`, `Who We'll Exclude`,
1292
- `Pass Rate`, `Recommendation`, and `Implementation Details`
1293
- - `message-validation.md` has `Status: confirmed`, `Mode: DRY MODE (no DB
1294
- mutation)`, a `Selected Winner`, and a non-empty `Token Adherence Table`
1295
- - `message-review.md` has `Status: message-review`, `Subject:`,
1296
- `Tokenized template:` with at least one literal `{{...}}` token,
1297
- `Sample prospect fill:` with a complete rendered subject + body and
1298
- `Token fill basis:`, `Rendered examples:`, `Good token fill:` with a complete
1299
- rendered subject + body, `Good omit:` with a complete rendered subject + body,
1300
- `Bad token fill:`, `Why bad:`, `Fallback if missing:`, `Token notes:`,
1301
- `My take:`, `Suggested adjustment:`, `Question:
1302
- approve-message or revise-messaging?`, and
1303
- `Recommendation: approve-message`
1304
- - `message-review-decision.md` is exactly `approve-message`
1305
-
1306
- Present the approval packet in user-facing order: brief, lead sample, lead
1307
- filter, message validation. Do not dump raw JSON or opaque validation
1308
- anchors at the user.
1309
-
1310
- When rendering the approval packet inline, start it with exactly
1311
- `Status: approval-packet`. Write the same content to `approval-packet.md`
1312
- before showing the gate. The same assistant turn must then use the structured
1313
- question gate with the six commit choices below. In Claude Code, call
1314
- `AskUserQuestion`; in Codex, call `request_user_input` when available. A
1315
- commit-gate question without the inline `Status: approval-packet` packet is
1316
- invalid UX. If a
1317
- customer roleplay is performed, write `customer-roleplay.md` before the final
1318
- choice. A roleplay result that says "looks good", "approve", or equivalent is
1319
- only critique; it does not satisfy the gate. Write `commit-gate-decision.md`
1320
- only after the user/operator makes one explicit choice.
1321
-
1322
- Use the structured question gate with exactly these 6 choices, in this order:
780
+ Before any auto-execute or validate-sample step, **load the dedicated tail subskill verbatim**:
1323
781
 
1324
- ```text
1325
- approve
1326
- revise-brief
1327
- revise-leads
1328
- revise-rubric
1329
- revise-messaging
1330
- abort
1331
782
  ```
1332
-
1333
- Do not collapse, reorder, or add choices. Do not auto-select.
1334
-
1335
- If the host UI caps options per question, preserve the same six routes with a
1336
- two-question gate: Q1 = `approve`, `revise`, `abort`; Q2 =
1337
- `revise-brief`, `revise-leads`, `revise-rubric`, `revise-messaging`. Do not
1338
- tell the customer this is because of schema/tool limits. In the split form,
1339
- `revise` is only the parent choice for the second question, not a new route.
1340
-
1341
- </commit_gate>
1342
-
1343
- <sender_resolution>
1344
-
1345
- Before atomic mint, the skill needs a concrete sender identity. Resolve
1346
- it in this order — stop at the first step that yields a confirmed
1347
- sender, and NEVER invent / guess / brute-force LinkedIn URLs:
1348
-
1349
- 1. **If the fixture/caller provides `senderIdentity.senderId`**, use it
1350
- directly. Call `get_sender({ senderId })` to confirm it exists in
1351
- the active workspace, then call `enrich_sender({ senderId })` ONCE
1352
- to populate `companySnapshot` + `proofDigest`. Do not call
1353
- `list_senders`, do not guess alternate URLs.
1354
- 2. **Else if the fixture/caller provides a confirmed
1355
- `senderIdentity.linkedinUrl`**, call `enrich_sender({ linkedinUrl
1356
- })` ONCE. If it errors, DO NOT retry with a variation of the URL.
1357
- Fall through to step 3.
1358
- 3. **Else if the caller provides `senderIdentity.name` +
1359
- `companyDomain` (or workspace context), do ONE `WebSearch` pass**
1360
- for the authoritative LinkedIn profile URL ("`{name}` `{company}`
1361
- linkedin"). Use ONLY a URL that appears verbatim in a web search
1362
- result. Never synthesize a URL from the name. If WebSearch returns
1363
- no clean match, escalate to step 4.
1364
- 4. **Else escalate.** Print the available sender context and ask the
1365
- user to resolve (senderId or confirmed linkedinUrl). Do not proceed
1366
- with atomic mint.
1367
-
1368
- Hard rules:
1369
-
1370
- - At most ONE `enrich_sender` retry per run, only when the first
1371
- response was a transient (5xx) error. Do not retry on 400/404 by
1372
- changing the URL.
1373
- - At most ONE `WebSearch` pass per run for sender resolution.
1374
- - NEVER call `enrich_sender` on a lead's LinkedIn URL. `enrich_sender`
1375
- is for the single sender entity only. Lead enrichment happens via
1376
- the Enrich Prospect column in the workflow table.
1377
- - If the fixture's `mustMatchWorkspaceSender` flag is true and the
1378
- resolved sender isn't in the active workspace, ABORT the run with an
1379
- explicit mismatch error.
1380
-
1381
- </sender_resolution>
1382
-
1383
- <atomic_mint>
1384
-
1385
- Only run this sequence when the user picks `approve`. Load
1386
- `references/watch-link-handoff.md` before starting; it owns the watch-link
1387
- surfacing protocol and the partial-mint recovery rules.
1388
-
1389
- Exact sequence:
1390
-
1391
- 1. Read `brief.md` and `rubric.json` from the draft directory.
1392
- 2. Validate anchors one more time. An empty anchor blocks the approve path.
1393
- The brief must include an `## Approved Message Template` section with
1394
- the exact live message template and at least one supported `{{token}}`
1395
- such as `{{first_name}}`. Rendered examples are not enough. The
1396
- Generate Message column switches to template mode only when
1397
- `campaignBrief.content` contains `{{...}}`; without this marker it will
1398
- use full-generation mode and may rewrite the approved message.
1399
- The live template body must contain only sender-ready copy plus supported
1400
- tokens. Two token shapes are allowed:
1401
- - `{{snake_case}}` field-substitution tokens for atomic values that drop
1402
- directly into a fixed slot (greeting, subject, company name).
1403
- - `[ALL_CAPS_NAME — Intent. DO: ... DON'T: ... FALLBACK: omit the line.]`
1404
- AI-native tokens for personalization sentences. The bracket carries
1405
- the contract inline; the model writes a sentence (or omits the line)
1406
- per the inline rules. Full spec:
1407
- `mcp/sellable/skills/create-campaign/references/ai-native-tokens.md`.
1408
- No other bracketed placeholders are allowed — bracketed prose without an
1409
- explicit Intent / DO / DON'T / FALLBACK contract (e.g., `[ROW BRIDGE]`,
1410
- `[insert ...]`, `[generated ...]`) is BLOCKED because it leaves the
1411
- per-row generation under-specified.
1412
- Include `## Token Fill Rules` for every token in the template. Field
1413
- tokens may be row fields such as `{{first_name}}`, `{{company}}`,
1414
- `{{role}}`, `{{headline}}`, `{{profile_summary}}`, `{{post_context}}`,
1415
- `{{comment_summary}}`, `{{source_post_topic}}`, or `{{row_proof_note}}`
1416
- when those exact fields are supported by the row/enrichment data. AI-native
1417
- tokens are listed in the rules table by name and type with a pointer back
1418
- to the inline contract (the rules themselves live inside the bracket — do
1419
- not duplicate them in the table). Do not document static sender identity,
1420
- product name, proof points, casing style, `{{recent_signal_quote}}`, or
1421
- abstract slot tokens such as `{{hookLine}}`, `{{painLine}}`,
1422
- `{{productLine}}`, `{{closeLine}}`, or `{{psLine}}` — those are abstract
1423
- slots without a contract; convert them to AI-native bracket tokens with
1424
- real Intent / DO / DON'T / FALLBACK clauses, or cut them.
1425
- Include `## Token Fill Examples` copied from the approved message review and
1426
- validation artifacts. It must preserve `Good token fill:`, `Good omit:`,
1427
- `Bad token fill:`, `Why bad:`, `Fallback if missing:`, and
1428
- `Token fill basis:` so the minted campaign brief teaches future row
1429
- generation how to fill tokens, what fills are blocked, and what to do when
1430
- row data is missing. If the brief does not contain `## Token Fill Rules` and
1431
- `## Token Fill Examples`, do not call `create_campaign`; route back to
1432
- message review or approval packet generation.
1433
- 3. Call `bootstrap_create_campaign({ flowVersion: "v2" })`. Respect
1434
- `safeToProceed`; on blocking errors, surface and stop.
1435
- 4. Call
1436
- `create_campaign({ campaignBrief, currentStep: "auto-execute-leads" })`.
1437
- The `campaignBrief` argument must preserve the approved message
1438
- template section verbatim, including the `{{tokens}}`.
1439
- If the brief has no supported `{{token}}`, do not call
1440
- `create_campaign`. Fail the approve path and ask for a corrected
1441
- template, unless the user explicitly approved freeform AI-generated
1442
- messages and the tool call sets `messageGenerationMode:
1443
- "ai-generated"`.
1444
- Include `senderIds` when a workspace sender is available. If the
1445
- customer-named sender is not configured in the current UAT workspace,
1446
- use an available workspace sender for the rehearsal and state that
1447
- mismatch in the final runtime notes. Do not silently mint without a
1448
- sender because sequence selection depends on sender tier/settings.
1449
- Capture `{ campaignId, watchUrl }` from the response.
1450
- - If the call errors, surface the error and stop. No rollback needed; no
1451
- campaign exists.
1452
- - If the response is missing `watchUrl`, treat it as a recoverable
1453
- failure. Stop before `save_rubrics`. Do not print a watch link.
1454
- Surface the contract violation explicitly — a missing `watchUrl` is a
1455
- plumbing bug, not a silent skip.
1456
- 5. Call `save_rubrics({ campaignOfferId: campaignId, rubric })` using the
1457
- payload derived from `rubric.json` (or from `lead-filter.md` if
1458
- `rubric.json` is absent).
1459
- - If this call fails after `create_campaign` succeeded, either rollback
1460
- the `CampaignOffer` row, or mark an explicit recoverable failure state
1461
- so the user can retry. Never leave a silent partial campaign. Do NOT
1462
- print the watch link during this recovery window.
1463
- 6. Flip the brief status in the draft to `committed`. Move the draft
1464
- directory from
1465
- `.sellable/create-campaign-v2/drafts/{workspace-slug}/{campaign-slug}/`
1466
- to
1467
- `.sellable/create-campaign-v2/drafts/{workspace-slug}/.committed/{campaign-slug}/`.
1468
- 7. Surface the `watchUrl` using the exact block defined in
1469
- `references/watch-link-handoff.md`. Only print after both
1470
- `create_campaign` AND `save_rubrics` have succeeded.
1471
- 8. Hand off to the autonomous tail (Plan 85-02). Do not run Step 13 lead
1472
- import here.
1473
-
1474
- If the approved lead source exists only as a provider lane in
1475
- `lead-review.md` (for example a Sales Navigator filter/search URL) and no
1476
- live `searchId` or `sourceLeadListId` is present, recreate the approved
1477
- source by calling the matching provider search tool first, then import from
1478
- the returned id. This is replaying the approved lane, not inventing a new
1479
- source. Do not skip import/messages on that basis.
1480
-
1481
- Do NOT call `import_leads` during atomic mint. Full lead sourcing and import
1482
- happen in Plan 85-02 Step 13 after mint.
1483
-
1484
- </atomic_mint>
1485
-
1486
- <revision_routing>
1487
-
1488
- When the user picks a revision choice, do not mint a campaign. Do not print
1489
- a watch link. Route back to the relevant upstream step and reset the draft
1490
- directory per `references/approval-gate-framing.md`:
1491
-
1492
- - `revise-brief` -> back to Phase 83 or Phase 84 depending on what changed.
1493
- Preserve `brief.md`; delete all downstream artifacts.
1494
- - `revise-leads` -> back to Phase 84 `find leads`. Preserve `brief.md`;
1495
- delete lead and downstream artifacts.
1496
- - `revise-rubric` -> back to Phase 84 `filter leads`. Preserve `brief.md`,
1497
- `lead-review.md`, `lead-sample.json`; delete `lead-filter.md`,
1498
- `message-validation.md`, and `rubric.json`.
1499
- - `revise-messaging` -> back to Phase 84 `generate message`. Preserve
1500
- upstream artifacts; delete only `message-validation.md`,
1501
- `message-review.md`, `message-review-decision.md`,
1502
- `customer-roleplay.md`, and `approval-packet.md`.
1503
- - `abort` -> move the draft directory to
1504
- `.sellable/create-campaign-v2/drafts/{workspace-slug}/.aborted/{campaign-slug}-{timestamp}/`.
1505
- No DB rows touched.
1506
-
1507
- Revisions must produce zero DB rows.
1508
-
1509
- </revision_routing>
1510
-
1511
- <boundaries>
1512
-
1513
- Phase 84 (pre-commit-gate) boundary:
1514
-
1515
- Do not create live campaign state during validation. Specifically, do not:
1516
-
1517
- - mint a campaign
1518
- - import leads
1519
- - persist selected lead lists
1520
- - attach downstream assets
1521
- - save remote rubric state
1522
- - move the user into a live execution step
1523
-
1524
- Phase 85 (commit-gate and beyond) boundary:
1525
-
1526
- - The commit gate is the only place in this skill where DB mutation is
1527
- authorized. Do not call `create_campaign`, `save_rubrics`,
1528
- `update_campaign`, or any other mutating tool before the user picks
1529
- `approve`.
1530
- - Revision choices and `abort` must never call a mutating tool.
1531
- - `import_leads` is not part of atomic mint. Defer it to Plan 85-02 Step 13.
1532
- - Never print the `watchUrl` until both `create_campaign` and `save_rubrics`
1533
- have succeeded.
1534
- - Never fabricate or reconstruct the `watchUrl` — capture it from the
1535
- `create_campaign` response.
1536
- - Once a campaign has been minted, every provider search and every
1537
- provider-import call from this skill MUST include the minted
1538
- `campaignOfferId`. This is universal — Prospeo, Sales Nav, Apollo,
1539
- Signal Discovery, and any future provider. The only place a
1540
- campaignless search is correct is the pre-mint Phase 84 `find leads`
1541
- discovery sample. Post-mint expansion, scale-up imports, alternate
1542
- lane explorations, account-based reruns, signal-monitor lanes, and
1543
- operator-driven follow-up searches all persist to the campaign and
1544
- must carry `campaignOfferId`. A search without `campaignOfferId`
1545
- after mint orphans the search from the campaign UI's Contact
1546
- Search panel and the campaign's `Searches` history, even when the
1547
- search produced rows that later get imported. If the search
1548
- helper enforces a `confirmed: true` gate, pass that with
1549
- `campaignOfferId` rather than dropping it.
1550
-
1551
- </boundaries>
1552
-
1553
- <autonomous_tail>
1554
-
1555
- The review-batch tail runs AFTER the atomic mint succeeds. It is driven by
1556
- `core/auto-execute.yaml` and progresses through four steps — Step 13
1557
- (import review batch), Step 14 (validate-sample), Step 15
1558
- (auto-execute-messaging for the review batch), Step 16
1559
- (awaiting-user-greenlight) — before stopping and waiting for a user
1560
- greenlight.
1561
-
1562
- Cost boundary: the commit gate approves creating a campaign and producing a
1563
- real review batch. It does NOT approve spending enrichment/message credits on
1564
- hundreds of leads. Two separate scales apply post-mint and they MUST be kept
1565
- distinct in your head:
1566
-
1567
- - **Import scale** (how many rows land in the campaign table). Defaults to
1568
- `import.importLimit` (25). The user MAY explicitly raise this at or before
1569
- mint with phrasing like "import all of them", "pull the full search", "all
1570
- ~2,000 from this lane", or a numeric target. When the user has stated the
1571
- full-scale import intent, pass that count as `targetLeadCount` so the table
1572
- carries the full pool. Importing rows is cheap (no enrichment runs yet);
1573
- storing them up front lets the user kick remaining enrichment manually
1574
- without re-importing later.
1575
- - **Cascade scale** (how many rows get enriched/scored/messaged before user
1576
- approval). ALWAYS stays at the configured review batch (`sample.sampleSize`
1577
- or `import.importLimit` — default 25) until the user explicitly approves the
1578
- sample. This is the cost gate. Even when the user said "import all", you
1579
- queue Enrich Prospect cells for only the first review-batch rows. The
1580
- remaining rows sit `pending` in the table for the user to kick manually
1581
- after they've eyeballed the sample.
1582
-
1583
- A pre-stated full-import intent is NOT a pre-approval to cascade everything.
1584
- Re-confirm before queueing enrichment beyond the review batch.
1585
-
1586
- If the source lane contains hundreds of leads and the user has not stated a
1587
- full-import intent, leave the rest untouched in the source — do not import
1588
- beyond `importLimit` until the user asks to expand.
1589
-
1590
- ## MANDATORY TOOL ORDER (read this BEFORE any tail step)
1591
-
1592
- Every tail run MUST call these tools in this exact order. The tail is
1593
- **review-batch cascade-driven**: you kick off Enrich Prospect only for
1594
- the imported review batch, and the workflow engine chains DNC Check →
1595
- ICP Score → Passes Rubric → Generate Message automatically. Your job is
1596
- to START the bounded cascade, WAIT for it to drain, OBSERVE the results,
1597
- and stop for review.
1598
- Do NOT manually run rubric-check, enrich, or message-generation
1599
- tools — the cascade already does them.
1600
-
1601
- ```text
1602
- Step 13 — import review batch + kick bounded cascade
1603
- import_leads(targetLeadCount=importLimit)
1604
- wait_for_lead_list_ready
1605
- confirm_lead_list
1606
- get_rows_minimal # capture enrichCellIds
1607
- queue_cells(cellIds=<review-batch Enrich Prospect cells only>) <-- starts bounded chain
1608
- wait_for_campaign_table_ready # review-batch cascade drains here
1609
- update_campaign(currentStep=validate-sample)
1610
-
1611
- Step 14 — observe sample
1612
- get_rows_minimal # read passesRubric + message cell status per row
1613
- compute projectedPass
1614
- if OK: update_campaign(currentStep=auto-execute-messaging)
1615
- else: diagnose brief-vs-list; if brief: update_campaign_brief + re-queue + wait
1616
- (check_rubric / bulk_enrich_with_prospeo are NOT called here —
1617
- cascade already did them. wait_for_rubric_results is OK as a
1618
- read-only observation helper if you need to block on completion.)
1619
-
1620
- Step 15 — observe messaging
1621
- get_rows_minimal # confirm passing rows have completed Generate Message cells
1622
- (rare) queue_cells on any pending Generate Message cells
1623
- token-contract spot check via get_rows
1624
- update_campaign(currentStep=awaiting-user-greenlight)
1625
- (generate_messages is NOT an MCP tool; messages come from the cascade)
1626
-
1627
- Step 16 — awaiting-user-greenlight
1628
- attach_recommended_sequence({ campaignId }) # tier-aware: premium/SN -> If Open Profile->INMAIL_OPEN, else INVITE->accepted->DM
1629
- re-surface watchUrl + review-batch orientation
1630
- STOP. DO NOT call start_campaign. DO NOT auto-advance currentStep.
783
+ mcp__sellable__get_subskill_prompt({ subskillName: "create-campaign-v2-tail" })
1631
784
  ```
1632
785
 
1633
- **Prefer `attach_recommended_sequence` over `attach_sequence` in the
1634
- autonomous tail.** The recommended tool takes only `campaignId` and
1635
- delegates template selection to the backend's tier-aware selector
1636
- (`selectTemplateForTiers`). `attach_sequence` requires you to
1637
- hand-author a `version: 2` template with nodes, branches, and
1638
- entryNodeId — that's error-prone mid-long-context (galley-off UAT
1639
- `20260420T195732Z` failed because Claude hit "Invalid node type" and
1640
- tried to debug via forbidden Bash/Glob calls). Use `attach_sequence`
1641
- only when the caller explicitly needs a custom non-recommended cadence.
1642
-
1643
- Hard gates — if you find yourself about to violate any of these, stop
1644
- first:
1645
-
1646
- - Do NOT use `update_cell` to write message bodies. The `Generate
1647
- Message` column's http_request writes those cells via the cascade.
1648
- `update_cell` remains reachable for legitimate operator overrides
1649
- AFTER the tail hands off.
1650
- - Do NOT call `check_rubric`, `enrich_with_prospeo`, or
1651
- `bulk_enrich_with_prospeo` in the tail. Those are direct-API
1652
- mutation tools that fetch data to the caller without writing to
1653
- the workflow table cells. Step 13's `queue_cells` already
1654
- triggers the column-level enrichment that populates those cells.
1655
- Running these tools in the tail produces duplicate cost with no
1656
- cell side effect.
1657
- - `wait_for_rubric_results` is read-only and OK to use as an
1658
- observation helper when you need to block on rubric completion —
1659
- it does not mutate cells. Prefer `get_rows_minimal` +
1660
- `wait_for_campaign_table_ready` for the primary cascade-drain
1661
- path, but use `wait_for_rubric_results({ targetCount: cohortSize })`
1662
- when the table-level wait returns before rubric cells finish.
1663
- - `start_campaign` is FORBIDDEN in the autonomous tail. It belongs only
1664
- in the Claude-greenlight path, AFTER the user signals "start". See
1665
- `references/final-handoff-contract.md`.
1666
- - You MAY NOT call `start_campaign` without a prior successful
1667
- `attach_recommended_sequence` (or `attach_sequence` if a custom
1668
- cadence is explicitly required) in the same run.
1669
- - You MAY NOT call `start_campaign` while ANY passing row has an
1670
- empty `Generate Message` cell. If you discover empty message cells in
1671
- the greenlight turn, ABORT greenlight and return to Step 15 first.
1672
- - You MAY NOT call `attach_sequence` while ANY passing row has an
1673
- empty `Generate Message` cell. Before `attach_sequence`, call
1674
- `get_rows_minimal` and confirm every row where `passesRubric=true`
1675
- has a `completed` Generate Message cell with non-empty `result`. If
1676
- any are pending, call `queue_cells` on those generateMessageCellIds
1677
- and wait. If rows truly won't message, ESCALATE.
1678
- - You MAY NOT advance past Step 13 without calling `queue_cells` on
1679
- the review-batch Enrich Prospect cells. Without it, every downstream
1680
- cell stays `pending` and the campaign ships empty.
1681
- - You MAY NOT queue enrichment for rows outside the configured review
1682
- batch before the user approves expansion. Full-list enrichment/message
1683
- generation is a credit-spend decision and must happen after the user
1684
- has reviewed the sample.
1685
-
1686
- Load `core/auto-execute.yaml` exactly once at the start of Step 13. All
1687
- subsequent steps read the already-parsed config. Do not re-load mid-run.
1688
- Load each subskill prompt (`create-campaign-v2`, `research-sender`,
1689
- `generate-messages`) at most once per run. A multi-call chunk sequence counts
1690
- as one load. If a tool result already told you to load a prompt, load all
1691
- chunks once and remember; do not restart the same prompt from offset 0 later.
1692
-
1693
- After every `update_campaign({ currentStep: ... })` in the tail, narrate
1694
- what changed and orient the user to what the watch link will show next —
1695
- reuse the v1 `create-campaign` watch-mode pattern verbatim.
1696
-
1697
- ## Step 13: auto-execute-leads
1698
-
1699
- Entered on `CampaignOffer.currentStep === "auto-execute-leads"` (set by
1700
- atomic mint).
1701
-
1702
- > Reminder: every provider search you run from this point forward — the
1703
- > review-batch source rerun in Step 13, any expansion search after the
1704
- > review batch, alternate-lane probes, account-based reruns, and operator
1705
- > follow-ups — MUST include `campaignOfferId`. This applies to
1706
- > `search_prospeo`, `search_sales_nav`, `search_apollo`,
1707
- > `search_signals`, and any other provider search tool added later.
1708
- > Campaignless searches after mint orphan results from the campaign UI.
1709
- >
1710
- > **Lead-list vs campaign-table identity rule (do not confuse them):**
1711
- > after the first `confirm_lead_list`, two workflow tables exist:
1712
- >
1713
- > - the **lead-list** table (the original `sourceLeadListId` returned by
1714
- > `import_leads`), and
1715
- > - the **campaign workflow table** (`CampaignOffer.workflowTableId`,
1716
- > also returned as `campaignTableId` from `confirm_lead_list`).
1717
- >
1718
- > `confirm_lead_list` overwrites `CampaignOffer.selectedLeadListId` with
1719
- > the campaign-table id. That means after the first confirm, the
1720
- > campaign-table id is NOT a valid `sourceLeadListId` for any future
1721
- > `import_leads` call.
1722
- >
1723
- > When you scale up the import, `mode: "add"` requires the ORIGINAL
1724
- > lead-list id (the one returned by the first `import_leads`), never the
1725
- > campaign-table id. Passing the campaign-table id silently writes
1726
- > straight into the campaign workflow table, bypassing the lead list
1727
- > entirely; the lead list stays at its original size and the
1728
- > campaign-builder `/leads` UI throws "Lead list not found" because it
1729
- > expects `selectedLeadListId` to resolve as a lead list.
1730
- >
1731
- > Capture the original `leadListId` from the FIRST `import_leads`
1732
- > response and reuse it for every scale-up `import_leads(mode: "add")`
1733
- > call on the same campaign. If the original id is unknown, query
1734
- > for the lead-list table by name or skip the `mode: "add"` path; do
1735
- > not pass the campaign-table id as `sourceLeadListId`.
1736
-
1737
- 1. Load `core/auto-execute.yaml`. Capture `import.importLimit`,
1738
- `sample.sampleSize`, `sample.minProjectedPass`,
1739
- `sample.maxRevisionRounds`, `messaging.tokenContract`,
1740
- `messaging.critique.enabled`, `handoff.autoStart`,
1741
- `handoff.orientation`, `retry.sameToolSameError`,
1742
- `logging.logEveryThresholdTrip`.
1743
- 2. Resolve the approved source before importing. If there is no
1744
- `lead-source-intake.json`, keep the existing discovered-provider path:
1745
- `import_leads({ campaignOfferId, targetLeadCount: importLimit })`.
1746
- If a manifest exists, branch by `sourceType`:
1747
- - `supplied-linkedin-profiles`: revalidate file metadata and confirmation
1748
- token, confirm `load_csv_linkedin_leads` only after approval to batch the
1749
- supplied CSV into a Sellable lead list, persist the returned `leadListId`,
1750
- then call `confirm_lead_list({ sourceLeadListId: leadListId,
1751
- targetLeadCount: importLimit })`. Do not call `import_leads` for this
1752
- branch; the lead list is the source, and `confirm_lead_list` imports the
1753
- bounded review batch into the campaign table.
1754
- - `existing-lead-list`: revalidate that the lead list still exists in the
1755
- same workspace, reuse it as `sourceLeadListId`, then call
1756
- `confirm_lead_list({ sourceLeadListId, targetLeadCount: importLimit })`.
1757
- - `supplied-domains`: reuse or confirm `load_csv_domains`, preserving
1758
- `domainFilterId`; run a campaign-associated Prospeo people search with
1759
- `campaignOfferId`, provider prompt preflight, and that `domainFilterId`;
1760
- then import with `targetLeadCount: importLimit`.
1761
- Never exceed `importLimit`. This is a review batch, not a full
1762
- campaign-scale import. If a source search/list contains more rows than
1763
- the cap, import only the first `importLimit` rows and leave the rest for
1764
- a later expansion step.
1765
- Persist or recover materialized IDs on resume: `leadListId`,
1766
- `domainFilterId`, `searchId`, `campaignTableId`, imported row IDs, and queued
1767
- cell IDs. If the source file changed after preview, or an existing lead list
1768
- is missing/wrong-workspace, escalate before materialization instead of
1769
- silently applying stale preview data. Retrying Step 13 must not duplicate
1770
- lead lists, searches, campaign rows, or queued cells.
1771
- 3. `wait_for_lead_list_ready` and `confirm_lead_list`.
1772
- 4. **Verify the table is set up properly before queuing.** Call
1773
- `get_rows_minimal({ tableId })` and confirm:
1774
- - `Enrich Prospect` column exists on the table and every imported
1775
- row has a corresponding cell with `status === "pending"`.
1776
- - `DNC Check`, `ICP Score`, `Passes Rubric`, and `Generate Message`
1777
- columns all exist too (the cascade depends on all of them).
1778
- - If any are missing, or the cell is in a non-`pending` terminal
1779
- state from an earlier run, ESCALATE with an explicit "table not
1780
- configured for autonomous tail" diagnosis. Do NOT attempt to
1781
- patch the table shape from the tail.
1782
- 5. **Kick off the bounded review-batch cascade.** `queue_cells({ tableId,
1783
- cellIds: <pending enrichCellIds for the imported review batch only> })`.
1784
- You queue ONLY the review-batch `Enrich Prospect` cells; the cascade
1785
- auto-dispatches `DNC Check`, `ICP Score`, `Passes Rubric`, and (for rows
1786
- where `Passes Rubric === true`) `Generate Message` as each upstream
1787
- completes. Do not queue cells for any rows beyond `importLimit` before
1788
- user expansion approval.
1789
- 6. `wait_for_campaign_table_ready` — waits for the review-batch cascade to
1790
- drain.
1791
- If it times out with most cells still `pending`, ESCALATE: the
1792
- engine is blocked.
1793
- 7. If the import returns zero usable leads, ESCALATE per
1794
- `references/escalation-ladder.md` (hard fail).
1795
- 8. `update_campaign({ campaignId, currentStep: "validate-sample" })`.
1796
- 9. Orient user on the watch link (same pattern as every other step
1797
- change).
1798
-
1799
- **Do NOT call `check_rubric`, `wait_for_rubric_results`,
1800
- `enrich_with_prospeo`, or `bulk_enrich_with_prospeo` in Step 13.**
1801
- Those are direct-API tools that fetch enrichment/scoring data to the
1802
- caller; they do not write to the workflow table cells. The cascade
1803
- triggered by `queue_cells` runs the `Enrich Prospect` column's
1804
- http_request, which writes the enrichment into the cell, which
1805
- triggers the next column, and so on. Running the direct-API tools
1806
- is duplicate work with no cell-population side effect.
1807
-
1808
- ## Step 14: validate-sample (loop)
1809
-
1810
- Entered on `CampaignOffer.currentStep === "validate-sample"`. Full
1811
- decision tree lives in `references/sample-validation-loop.md`.
1812
-
1813
- **Step 14 is pure observation.** The bounded review-batch cascade that Step
1814
- 13 kicked off (via `queue_cells` on Enrich Prospect) has already written ICP
1815
- scores and Passes Rubric values back into the workflow table. Step 14 reads
1816
- those review-batch cell results — it does NOT call `check_rubric`,
1817
- `wait_for_rubric_results`, `bulk_enrich_with_prospeo`, or any other
1818
- direct enrichment/scoring tool. All of that already happened in the
1819
- cascade; running them again is wasted work and can overwrite the
1820
- real cell results with unrelated data.
1821
-
1822
- Shape:
1823
-
1824
- ```text
1825
- get_rows_minimal({ tableId })
1826
- passInSample = count of first sampleSize review-batch rows with passesRubric === true
1827
- projectedPass = round(passInSample / sampleSize * importLimit)
1828
-
1829
- if projectedPass >= minProjectedPass:
1830
- advance to Step 15
1831
- else:
1832
- diagnose brief-vs-list per sample-validation-loop.md
1833
- - brief: autonomous update_campaign_brief, then re-kick cascade
1834
- (queue_cells on enrichCellIds) and wait for the new
1835
- results
1836
- - list: ESCALATE (no auto-revision of leads)
1837
- - unknown: ESCALATE
1838
- revisionRound += 1
1839
- if revisionRound > maxRevisionRounds:
1840
- ESCALATE
1841
- ```
786
+ Follow that prompt verbatim. It contains the canonical MANDATORY TOOL ORDER (read this BEFORE any tail step), all Step 13-16 contracts, threshold-trip logging rules, and tail hard rules.
1842
787
 
1843
- Persisted counter rule: `revisionRound` persists across skill resume.
1844
- Do NOT reset to 0 on resume — a stale resume must still respect the
1845
- `maxRevisionRounds` cap.
1846
-
1847
- A "list problem" diagnosis NEVER triggers autonomous
1848
- `update_campaign_brief`. Escalate instead.
1849
-
1850
- When the sample passes the projected-pass floor, call
1851
- `update_campaign({ campaignId, currentStep: "auto-execute-messaging" })`
1852
- and orient the user that messaging will complete for the review batch only.
1853
-
1854
- ## Step 15: auto-execute-messaging
1855
-
1856
- Entered on `CampaignOffer.currentStep === "auto-execute-messaging"`.
1857
-
1858
- **Messages are produced by the `Generate Message` column cascade, not
1859
- by a separate tool.** Do NOT call a `generate_messages` MCP tool —
1860
- that tool does not exist; `generate-messages` is a subskill prompt
1861
- loaded during live messaging drafts. In the autonomous tail, messages
1862
- flow through the column pipeline: `Enrich Prospect` →
1863
- `DNC Check` → `ICP Score` → `Passes Rubric` → `Generate Message`.
1864
- Each column's http_request auto-fires when its upstream dependency
1865
- completes AND passes gate (e.g. `Passes Rubric === true` before
1866
- `Generate Message`). Your job in Step 15 is to WAIT for the review-batch
1867
- cascade to reach `Generate Message` for rows that passed ICP, and verify
1868
- the output — not to generate messages manually.
1869
-
1870
- **What Step 15 does:**
1871
-
1872
- 1. `get_rows_minimal` to read `passesRubric` + `generateMessageCellId`
1873
- - the Generate Message cell's `status` and `result` per row.
1874
- Before queueing or waiting on Generate Message cells, confirm the
1875
- minted campaign brief still contains `{{...}}` in `## Approved Message
1876
- Template`. If it does not, fail before the cascade runs. Do not repair
1877
- after mint; the template must be present during mint so Step 15 never
1878
- starts in freeform generation mode.
1879
- 2. For every row where `passesRubric === true`:
1880
- - The Generate Message cell should be `running` or `completed`
1881
- already (cascade auto-fired it). If it is still `pending`, queue
1882
- it explicitly: `queue_cells({ tableId, cellIds:
1883
- <generateMessageCellIds> })`.
1884
- 3. `wait_for_campaign_table_ready` (or poll) until every passing
1885
- row's Generate Message cell is `completed`.
1886
- 4. Read the results back via `get_rows` (full) and sanity-check a
1887
- sample against the Phase 84 token contract: no unresolved
1888
- `{{tokens}}`, no invented proof, one sentence per line, etc.
1889
- 5. If the sample fails the token contract, diagnose brief-vs-list
1890
- (same revision loop as Step 14) and escalate if over
1891
- `maxRevisionRounds`.
1892
- 6. On success, `update_campaign({ campaignId, currentStep:
1893
- "awaiting-user-greenlight" })`.
1894
-
1895
- **Do NOT hand-write message bodies via `update_cell`.** `update_cell`
1896
- is reachable for legitimate operator overrides AFTER the tail hands
1897
- off, but during autonomous tail the cascade owns the writes. If you
1898
- find yourself drafting a message body and about to push it through
1899
- `update_cell`, you have lost state — stop, read the cells, and let
1900
- the pipeline finish.
1901
-
1902
- **What `attach_sequence` does (Step 16, not here):** binds the
1903
- DM/InMail cadence template to the workflow table. Completely different
1904
- job from messaging. Does NOT generate or write message text. A
1905
- sequence with no `Generate Message` outputs would try to send empty
1906
- strings, which is why Step 16 requires Step 15 to be complete.
1907
-
1908
- 1. Observe the review-batch messages on the same sample that passed
1909
- validation.
1910
- 2. If `messaging.critique.enabled` is true (Plan 85-03), run the
1911
- bounded critique pass on the sample output per
1912
- `references/parallel-critique-protocol.md`. The pass runs on at
1913
- most `messaging.critique.sampleSize` rows, sends each row through
1914
- three parallel critics (targeting / copy / voice) that return
1915
- structured JSON, and merges the voices in a synthesis step that
1916
- enforces the Phase 84 token contract verbatim and re-runs the
1917
- finalizer pass. Any rewrite that invents proof or uses an
1918
- unsupported token falls back to the plain generated message. A
1919
- trip of `messaging.critique.budgetUsdCap` HALTS critique for the
1920
- remaining sample and continues the plain tail. Plan 85-02 reads
1921
- the flag but never flips it; critique stays off until the flag is
1922
- deliberately enabled.
1923
- 3. If `messaging.critique.opus.enabled` is also true, route the
1924
- highest-value subset through the Opus / craft-message path per
1925
- `references/thomas-variant-selection.md`. Opus is capped by
1926
- `messaging.critique.opus.maxMessagesPerPass` and
1927
- `messaging.critique.opus.budgetUsdCap`; tripping either cap keeps
1928
- the remaining rows on the non-Opus synthesizer. Opus is bound by
1929
- the same token contract as every other rewrite path.
1930
- 4. Check `messaging.tokenContract`. When `strict`, reject any sample
1931
- message that contains unresolved or unsupported tokens (including
1932
- any critique rewrite that tried to introduce one).
1933
- 5. If the sample passes the token contract (and critique when enabled),
1934
- stop at the review-batch handoff. Do NOT scale to the full source list
1935
- before explicit user expansion approval.
1936
- 6. If the sample fails the token contract or critique, diagnose +
1937
- loop the same way Step 14 does (brief-vs-list), subject to the same
1938
- `maxRevisionRounds` cap.
1939
- 7. On success, `update_campaign({ campaignId, currentStep:
1940
- "awaiting-user-greenlight" })` and orient the user.
1941
-
1942
- Critique failure modes NEVER escalate. A critic timeout, a total
1943
- timeout, a budget trip, a fake-proof rejection, or an unsupported-
1944
- token rejection all fall back to the plain generated message for that
1945
- row. Step 15 does not stall on critique.
1946
-
1947
- ## Step 16: awaiting-user-greenlight
1948
-
1949
- Entered on `CampaignOffer.currentStep === "awaiting-user-greenlight"`.
1950
- Full contract lives in `references/final-handoff-contract.md`.
1951
-
1952
- Shape:
1953
-
1954
- 1. `attach_sequence` (bind the committed sequence to the campaign).
1955
- 2. Re-surface the `watchUrl` using `references/watch-link-handoff.md`.
1956
- 3. Surface the `handoff.orientation` string from `auto-execute.yaml`
1957
- alongside the link.
1958
- 4. STOP. Do NOT call `start_campaign`. Do NOT auto-advance
1959
- `currentStep`. The autonomous tail ends here.
1960
- 5. Make the credit boundary explicit in the handoff: only the first review
1961
- batch has been enriched/messaged; expanding to more leads requires a
1962
- separate user instruction.
1963
-
1964
- Two equally valid greenlight channels take Step 16 into a running
1965
- campaign:
1966
-
1967
- - **UI path** — user clicks "Approve all" and "Start Campaign" in the
1968
- watch-link UI. The skill stays idle. On the next resume, it observes
1969
- the running state and shifts to a "campaign is live" confirmation.
1970
- - **Claude greenlight path** — user replies with an affirmative ("yeah
1971
- start" / "looks good, start" / "ship it"). The skill then performs,
1972
- in order: (a) bulk-approve queued messages via the EXISTING endpoint
1973
- `POST /api/v3/workflow-tables/cells/approve-batch` (do NOT invent a
1974
- new tool/endpoint), (b) `start_campaign({ campaignId })`, (c)
1975
- `update_campaign({ campaignId, currentStep: "running" })`, (d)
1976
- re-surface `watchUrl` plus a "campaign is live" confirmation.
1977
-
1978
- A Claude greenlight on an already-running campaign is a no-op
1979
- confirmation, NOT a duplicate start. Detect via `get_campaign` before
1980
- calling any mutating tool; if the campaign is already running, skip
1981
- approve-batch / start_campaign / update_campaign and just confirm.
1982
-
1983
- Workspace/sender mismatch at greenlight time aborts the start with the
1984
- same invariant Phase 84 enforces.
1985
-
1986
- ## Threshold Trips and Logging
1987
-
1988
- When `logging.logEveryThresholdTrip === true` (default), log every
1989
- threshold trip: `projectedPass` computation, retry cap, revision cap,
1990
- hard-fail. These logs drive `auto-execute.yaml` tuning after 3-5 real
1991
- runs.
1992
-
1993
- ## Tail Hard Rules
1994
-
1995
- - Review-batch sourcing/import happens in Step 13, not during atomic mint.
1996
- - Full-list expansion is not part of the default tail. It requires user
1997
- approval after the review batch.
1998
- Import must never exceed `importLimit`.
1999
- - The tail NEVER calls `start_campaign` on its own.
2000
- - The tail NEVER auto-revises leads. Brief revision is autonomous; lead
2001
- revision is always operator-gated.
2002
- - `revisionRound` persists across resume — no silent reset.
2003
- - The bulk-approve action in the Claude greenlight path uses the
2004
- existing `POST /api/v3/workflow-tables/cells/approve-batch` endpoint
2005
- — do NOT create a new tool or endpoint for this.
2006
- - Threshold trips are logged for calibration.
2007
-
2008
- </autonomous_tail>
2009
-
2010
- <references_index>
2011
-
2012
- | File | Load when |
2013
- | ------------------------------------------ | ---------------------------------------------------------------------- |
2014
- | `references/approval-gate-framing.md` | Phase 85 commit gate, before showing the approval packet |
2015
- | `references/watch-link-handoff.md` | Atomic mint + every tail resume, before surfacing watchUrl |
2016
- | `references/sample-validation-loop.md` | Step 14, before enriching + scoring the sample |
2017
- | `references/escalation-ladder.md` | Any tail step that needs to decide retry / revise / escalate |
2018
- | `references/final-handoff-contract.md` | Step 16, and every Claude greenlight turn |
2019
- | `references/parallel-critique-protocol.md` | Step 15 when `messaging.critique.enabled` is true |
2020
- | `references/thomas-variant-selection.md` | Step 15 when `messaging.critique.opus.enabled` is true |
2021
- | `references/thomas-revision-filters.md` | Any critique rewrite, before persisting |
2022
- | `core/auto-execute.yaml` | Start of Step 13, load once; all tail steps read parsed values |
2023
- | `core/auto-execute.README.md` | When tuning `auto-execute.yaml` knobs or reviewing threshold-trip logs |
2024
-
2025
- </references_index>
788
+ Do NOT invoke any tail tool (auto_execute_leads, validate_sample, auto_execute_messaging, etc.) without first loading this subskill — the tool order and the threshold-trip checks live there.