@signaliz/sdk 1.0.13 → 1.0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1704,6 +1704,16 @@ var CampaignBuilderAgent = class {
1704
1704
  const plan = await this.createPlan(request, options);
1705
1705
  return createCampaignBuilderReadiness(plan);
1706
1706
  }
1707
+ async proof(request, options = {}) {
1708
+ const plan = await this.createPlan(request, options);
1709
+ const result = await this.dryRunPlan(plan, {
1710
+ idempotencyKey: options.idempotencyKey
1711
+ });
1712
+ return createCampaignBuilderProofReceipt(plan, result);
1713
+ }
1714
+ buildKit(options = {}) {
1715
+ return createCampaignBuilderBuildKit(options);
1716
+ }
1707
1717
  async commitPlan(plan, options = {}) {
1708
1718
  const writeMode = options.confirm === true && options.dryRun === false;
1709
1719
  if (writeMode && !options.approvedBy) {
@@ -2149,6 +2159,72 @@ function createCampaignBuilderReadiness(plan) {
2149
2159
  nextActions: campaignReadinessNextActions(plan, ready, customRoutes.length)
2150
2160
  };
2151
2161
  }
2162
+ function createCampaignBuilderProofReceipt(plan, result) {
2163
+ const strategyMemory = asRecord(plan.strategyMemoryStatus);
2164
+ const dryRunResult = asRecord(result);
2165
+ const memoryReady = plan.strategyMemoryStatus ? strategyMemory.ready !== false : false;
2166
+ const dryRunCompleted = dryRunResult.dryRun === true || dryRunResult.dry_run === true || dryRunResult.status === "dry_run";
2167
+ const noLaunch = dryRunCompleted && !dryRunResult.campaignBuildId && !dryRunResult.campaign_build_id;
2168
+ const gates = [
2169
+ {
2170
+ id: "strategy_memory_ready",
2171
+ passed: memoryReady,
2172
+ ready: strategyMemory.ready ?? null,
2173
+ blocker_count: Array.isArray(strategyMemory.blockers) ? strategyMemory.blockers.length : 0
2174
+ },
2175
+ {
2176
+ id: "campaign_plan_ready",
2177
+ passed: Boolean(plan.planId && plan.mcpFlow.length > 0),
2178
+ plan_id: plan.planId,
2179
+ flow_steps: plan.mcpFlow.length
2180
+ },
2181
+ {
2182
+ id: "approval_gates_present",
2183
+ passed: plan.approvals.length > 0,
2184
+ approval_types: plan.approvals.map((approval) => approval.type)
2185
+ },
2186
+ {
2187
+ id: "dry_run_completed",
2188
+ passed: dryRunCompleted,
2189
+ status: dryRunResult.status ?? null,
2190
+ current_phase: dryRunResult.currentPhase ?? dryRunResult.current_phase ?? null
2191
+ },
2192
+ {
2193
+ id: "no_spendful_launch",
2194
+ passed: noLaunch,
2195
+ campaign_build_id: dryRunResult.campaignBuildId ?? dryRunResult.campaign_build_id ?? null
2196
+ }
2197
+ ];
2198
+ return {
2199
+ receipt_version: "campaign-agent-proof.v1",
2200
+ source: "signaliz.campaignBuilderAgent.proof",
2201
+ success: gates.every((gate) => gate.passed),
2202
+ safety: {
2203
+ spendful_tools_called: false,
2204
+ external_writes_called: false,
2205
+ sender_loads_called: false,
2206
+ email_sends_called: false,
2207
+ dry_run_only: true
2208
+ },
2209
+ campaign: {
2210
+ plan_id: plan.planId,
2211
+ campaign_name: plan.campaignName,
2212
+ strategy_template: campaignBuilderProofStrategyTemplate(plan),
2213
+ target_count: plan.targetCount,
2214
+ estimated_credits: plan.estimatedCredits,
2215
+ operating_playbooks: plan.operatingPlaybooks.map((playbook) => playbook.slug)
2216
+ },
2217
+ gates,
2218
+ strategy_memory_status: summarizeCampaignBuilderProofStrategyMemory(strategyMemory),
2219
+ dry_run_result: summarizeCampaignBuilderProofDryRun(dryRunResult),
2220
+ recommended_next_actions: [
2221
+ "Review the plan, approvals, and dry-run result.",
2222
+ "Use campaign-agent commit-plan --confirm-write only after review.",
2223
+ "Use campaign-agent build-approved only with --confirm-launch, approval identity, approval types, and spend limit.",
2224
+ "When an approved build reaches pending_approval, review rows and approve delivery through the Campaigns SDK."
2225
+ ]
2226
+ };
2227
+ }
2152
2228
  function getMissingCampaignBuilderApprovals(plan, approval) {
2153
2229
  if (approval.planId !== plan.planId) {
2154
2230
  return plan.approvals;
@@ -2302,6 +2378,156 @@ function createCampaignBuilderAgentRequestTemplate(input = {}) {
2302
2378
  }
2303
2379
  });
2304
2380
  }
2381
+ function createCampaignBuilderBuildKit(input = {}) {
2382
+ const requestFile = input.requestFile || "campaign-request.json";
2383
+ const cliPackage = input.cliPackage || "@signaliz/cli";
2384
+ const sdkPackage = input.sdkPackage || "@signaliz/sdk";
2385
+ const request = createCampaignBuilderAgentRequestTemplate(input);
2386
+ const strategyTemplate = stringValue(request.strategyTemplate) ?? null;
2387
+ const builtIns = request.builtIns ?? DEFAULT_CAMPAIGN_BUILDER_BUILT_INS;
2388
+ const useLocalLeads = builtIns.includes("local_leads");
2389
+ const customRoutes = [
2390
+ ...request.integrations ?? [],
2391
+ ...routesFromCustomerTools(request.customerTools ?? [])
2392
+ ].filter((route) => route.provider !== "signaliz");
2393
+ const strategyFlag = strategyTemplate ? ` --strategy-template ${shellArg(strategyTemplate)}` : "";
2394
+ const targetFlag = request.targetCount ? ` --target-count ${request.targetCount}` : "";
2395
+ const localLeadsFlag = useLocalLeads ? " --use-local-leads" : "";
2396
+ const cliBase = `npx ${cliPackage}`;
2397
+ const sdkCliBase = `npx ${sdkPackage}`;
2398
+ const brief = request.goal || "Build a strategy-template campaign for the target ICP.";
2399
+ const mcpArgs = campaignBuilderBuildKitMcpArgs(request);
2400
+ return {
2401
+ kit_version: "campaign-builder-kit.v1",
2402
+ source: "signaliz.campaignBuilderAgent.buildKit",
2403
+ request_file: requestFile,
2404
+ request,
2405
+ strategy_template: strategyTemplate,
2406
+ built_in_lanes: builtIns,
2407
+ operating_playbooks: getCampaignBuilderOperatingPlaybooksForRequest(request).map((playbook) => playbook.slug),
2408
+ custom_routes: customRoutes.map((route) => ({
2409
+ provider: String(route.provider),
2410
+ layer: String(route.layer),
2411
+ tool: firstNonEmptyString(route.toolName),
2412
+ mcp_server: firstNonEmptyString(route.mcpServerName),
2413
+ mode: route.mode ?? "if_available",
2414
+ approval_required: route.approvalRequired === true || route.mode === "required"
2415
+ })),
2416
+ approval_boundaries: request.approvalPolicy?.requireApprovalFor ?? DEFAULT_CAMPAIGN_BUILDER_APPROVAL_TYPES,
2417
+ byo_tool_pattern: {
2418
+ cli_flag: "--custom-tool provider:layer:tool[:mcp]",
2419
+ request_fragment: createCampaignBuilderToolRoute({
2420
+ provider: "workspace_mcp",
2421
+ layer: "enrichment",
2422
+ gtmLayers: ["company_enrichment"],
2423
+ toolName: "workspace_account_enrich",
2424
+ mcpServerName: "workspace-mcp",
2425
+ label: "Workspace account enrichment",
2426
+ mode: "required",
2427
+ approvalRequired: true
2428
+ })
2429
+ },
2430
+ cli_commands: [
2431
+ {
2432
+ id: "write_request",
2433
+ label: "Write reusable request JSON",
2434
+ command: `${cliBase} campaign-agent init${strategyFlag}${targetFlag}${localLeadsFlag} --output-file ${shellArg(requestFile)}`,
2435
+ safety: "local file only; no MCP calls, credits, provider writes, sender loads, exports, or sends"
2436
+ },
2437
+ {
2438
+ id: "proof_shortcut",
2439
+ label: "Run no-spend campaign-builder proof",
2440
+ command: `${cliBase} build ${shellArg(brief)}${strategyFlag}${targetFlag}${localLeadsFlag} --json`,
2441
+ safety: "strategy memory, Kernel plan, approvals, and forced build_campaign dry-run only"
2442
+ },
2443
+ {
2444
+ id: "plan",
2445
+ label: "Inspect the full campaign-agent plan",
2446
+ command: `${sdkCliBase} campaign-agent plan --request-file ${shellArg(requestFile)} --json`,
2447
+ safety: "read-only MCP planning and provider-route dry-runs"
2448
+ },
2449
+ {
2450
+ id: "doctor",
2451
+ label: "Check readiness gates",
2452
+ command: `${sdkCliBase} campaign-agent doctor --request-file ${shellArg(requestFile)} --json`,
2453
+ safety: "read-only readiness checks for Memory, Brain, built-ins, BYO routes, and approvals"
2454
+ },
2455
+ {
2456
+ id: "commit_preview",
2457
+ label: "Preview GTM campaign object commit",
2458
+ command: `${sdkCliBase} campaign-agent commit-plan --request-file ${shellArg(requestFile)} --json`,
2459
+ safety: "dry-run commit; writes only with --confirm-write and --approved-by"
2460
+ },
2461
+ {
2462
+ id: "approved_launch",
2463
+ label: "Launch after explicit approval",
2464
+ command: `${sdkCliBase} campaign-agent build-approved --request-file ${shellArg(requestFile)} --confirm-launch --approve-all --approved-by operator@example.com --spend-limit ${request.signalizDefaults?.maxCredits ?? 0} --json`,
2465
+ safety: "spendful path; requires human approval identity, approval types, and spend limit"
2466
+ }
2467
+ ],
2468
+ mcp_calls: [
2469
+ {
2470
+ id: "request_template",
2471
+ tool: "gtm_campaign_agent_request_template",
2472
+ arguments: mcpArgs,
2473
+ safety: "read-only reusable request generation"
2474
+ },
2475
+ {
2476
+ id: "readiness",
2477
+ tool: "gtm_campaign_agent_readiness",
2478
+ arguments: mcpArgs,
2479
+ safety: "read-only preflight across strategy memory, Kernel plan, lanes, routes, and approvals"
2480
+ },
2481
+ {
2482
+ id: "proof",
2483
+ tool: "gtm_campaign_agent_proof",
2484
+ arguments: { ...mcpArgs, idempotency_key: "campaign-agent-proof-001" },
2485
+ safety: "forces build_campaign dry_run=true and confirm_spend=false"
2486
+ },
2487
+ {
2488
+ id: "plan",
2489
+ tool: "gtm_campaign_agent_plan",
2490
+ arguments: mcpArgs,
2491
+ safety: "read-only one-call campaign-agent runbook"
2492
+ },
2493
+ {
2494
+ id: "commit_preview",
2495
+ tool: "gtm_campaign_build_plan_commit",
2496
+ arguments: {
2497
+ name: request.campaignName,
2498
+ campaign_brief: request.goal,
2499
+ lead_count: request.targetCount,
2500
+ dry_run: true,
2501
+ confirm: false
2502
+ },
2503
+ safety: "dry-run commit preview only"
2504
+ }
2505
+ ],
2506
+ sdk_example: {
2507
+ language: "typescript",
2508
+ code: campaignBuilderBuildKitSdkExample(request, requestFile)
2509
+ },
2510
+ verification: [
2511
+ `${cliBase} campaign-agent proof --request-file ${shellArg(requestFile)} --json`,
2512
+ `${cliBase} campaign-agent doctor --request-file ${shellArg(requestFile)} --json`,
2513
+ "Confirm proof.success is true and dry_run_result.status is dry_run before any approved launch.",
2514
+ "Confirm no campaign_build_id exists in a proof receipt before moving to approved launch."
2515
+ ],
2516
+ privacy: {
2517
+ client_names_allowed: false,
2518
+ notes: [
2519
+ "Use strategy templates, operating playbooks, and anonymized workflow patterns instead of client names.",
2520
+ "Do not include raw leads, private replies, domains, secrets, or customer account labels in public kit output."
2521
+ ]
2522
+ },
2523
+ next_actions: [
2524
+ `Write or review ${requestFile}.`,
2525
+ "Run the proof command before spending credits or activating provider writes.",
2526
+ "Add BYO integrations with --custom-tool provider:layer:tool[:mcp] or the request_fragment shape.",
2527
+ "Use build-approved only after human approval, spend limit, and delivery review policy are set."
2528
+ ]
2529
+ };
2530
+ }
2305
2531
  function createCampaignBuilderToolRoute(input) {
2306
2532
  return {
2307
2533
  provider: input.provider ?? "custom_mcp",
@@ -2317,6 +2543,63 @@ function createCampaignBuilderToolRoute(input) {
2317
2543
  rationale: `${input.label ?? input.provider ?? "Custom tool"} is a user-provided campaign-builder route for ${input.layer}.`
2318
2544
  };
2319
2545
  }
2546
+ function campaignBuilderBuildKitMcpArgs(request) {
2547
+ return compact({
2548
+ goal: request.goal,
2549
+ campaign_brief: request.goal,
2550
+ campaign_name: request.campaignName,
2551
+ account_label: request.accountLabel,
2552
+ account_context: request.accountContext,
2553
+ strategy_template: request.strategyTemplate,
2554
+ operating_playbooks: request.operatingPlaybooks,
2555
+ target_icp: request.icp,
2556
+ target_count: request.targetCount,
2557
+ builtins: request.builtIns,
2558
+ include_local_leads: request.builtIns?.includes("local_leads") || void 0,
2559
+ preferred_providers: request.preferredProviders,
2560
+ custom_tools: request.integrations?.map((route) => compact({
2561
+ provider: route.provider,
2562
+ layer: route.layer,
2563
+ gtm_layers: route.gtmLayers ?? (route.gtmLayer ? [route.gtmLayer] : void 0),
2564
+ tool: route.toolName,
2565
+ mcp: route.mcpServerName,
2566
+ mode: route.mode,
2567
+ approval_required: route.approvalRequired
2568
+ })),
2569
+ include_nango_catalog: request.agencyContext?.includeNangoCatalog,
2570
+ include_memory: request.memory?.enabled,
2571
+ include_brain: true,
2572
+ include_provider_routes: true,
2573
+ include_delivery_risk: true
2574
+ });
2575
+ }
2576
+ function campaignBuilderBuildKitSdkExample(request, requestFile) {
2577
+ const proofRequest = {
2578
+ goal: request.goal,
2579
+ strategyTemplate: request.strategyTemplate,
2580
+ targetCount: request.targetCount,
2581
+ builtIns: request.builtIns,
2582
+ integrations: request.integrations
2583
+ };
2584
+ return [
2585
+ "import { Signaliz, createCampaignBuilderBuildKit } from '@signaliz/sdk';",
2586
+ "",
2587
+ `const kit = createCampaignBuilderBuildKit({ requestFile: ${JSON.stringify(requestFile)}, ...${JSON.stringify(proofRequest, null, 2)} });`,
2588
+ "console.log(kit.cli_commands.find((command) => command.id === 'proof_shortcut')?.command);",
2589
+ "",
2590
+ "const signaliz = new Signaliz({ apiKey: process.env.SIGNALIZ_API_KEY! });",
2591
+ "const proof = await signaliz.campaignBuilderAgent.proof(kit.request, {",
2592
+ " idempotencyKey: `campaign-agent-proof-${Date.now()}`,",
2593
+ "});",
2594
+ "",
2595
+ 'if (!proof.success || proof.dry_run_result?.status !== "dry_run") {',
2596
+ " throw new Error('Campaign proof failed or launched work unexpectedly');",
2597
+ "}"
2598
+ ].join("\n");
2599
+ }
2600
+ function shellArg(value) {
2601
+ return `'${value.replace(/'/g, "'\\''")}'`;
2602
+ }
2320
2603
  function normalizeTemplateKey(value) {
2321
2604
  return String(value || "").trim().toLowerCase().replace(/[_\s]+/g, "-");
2322
2605
  }
@@ -3591,6 +3874,72 @@ function campaignReadinessNextActions(plan, ready, customRouteCount) {
3591
3874
  ];
3592
3875
  return actions.filter((item) => Boolean(item));
3593
3876
  }
3877
+ function campaignBuilderProofStrategyTemplate(plan) {
3878
+ const buildRequest = asRecord(plan.buildRequest);
3879
+ const strategyMemory = asRecord(plan.strategyMemoryStatus);
3880
+ const statusTemplate = strategyMemory.strategy_template ?? strategyMemory.strategyTemplate;
3881
+ const statusTemplateRecord = asRecord(statusTemplate);
3882
+ const flowTemplate = plan.mcpFlow.map((step) => asRecord(step.arguments).strategy_template ?? asRecord(step.arguments).strategyTemplate).find((value) => typeof value === "string" && value.trim());
3883
+ return firstNonEmptyString(
3884
+ buildRequest.strategyTemplate,
3885
+ buildRequest.strategy_template,
3886
+ statusTemplate,
3887
+ statusTemplateRecord.slug,
3888
+ statusTemplateRecord.id,
3889
+ flowTemplate
3890
+ );
3891
+ }
3892
+ function summarizeCampaignBuilderProofStrategyMemory(strategyMemory) {
3893
+ if (Object.keys(strategyMemory).length === 0) return { ready: false };
3894
+ const template = strategyMemory.strategy_template ?? strategyMemory.strategyTemplate;
3895
+ const templateRecord = asRecord(template);
3896
+ const coverage = asRecord(strategyMemory.coverage);
3897
+ const rawSourceGroups = Array.isArray(strategyMemory.source_groups) ? strategyMemory.source_groups : Array.isArray(strategyMemory.sourceGroups) ? strategyMemory.sourceGroups : [];
3898
+ const sourceGroups = rawSourceGroups.map((group) => {
3899
+ const sourceGroup = asRecord(group);
3900
+ return {
3901
+ id: sourceGroup.id ?? null,
3902
+ required: sourceGroup.required ?? null,
3903
+ ready: sourceGroup.ready ?? null,
3904
+ counts: asRecord(sourceGroup.counts)
3905
+ };
3906
+ });
3907
+ return {
3908
+ ready: strategyMemory.ready ?? null,
3909
+ read_only: strategyMemory.read_only ?? strategyMemory.readOnly ?? null,
3910
+ source_tool: firstNonEmptyString(strategyMemory.source_tool, strategyMemory.sourceTool),
3911
+ strategy_template: {
3912
+ slug: firstNonEmptyString(template, templateRecord.slug, templateRecord.id),
3913
+ label: firstNonEmptyString(templateRecord.label)
3914
+ },
3915
+ coverage: {
3916
+ required_groups_ready: coverage.required_groups_ready ?? coverage.requiredGroupsReady ?? null,
3917
+ required_groups_total: coverage.required_groups_total ?? coverage.requiredGroupsTotal ?? null,
3918
+ source_groups_ready: coverage.source_groups_ready ?? coverage.sourceGroupsReady ?? null,
3919
+ source_groups_total: coverage.source_groups_total ?? coverage.sourceGroupsTotal ?? null,
3920
+ knowledge_docs: coverage.knowledge_docs ?? coverage.knowledgeDocs ?? null,
3921
+ memories: coverage.memories ?? null
3922
+ },
3923
+ source_groups: sourceGroups,
3924
+ blocker_count: Array.isArray(strategyMemory.blockers) ? strategyMemory.blockers.length : 0,
3925
+ warning_count: Array.isArray(strategyMemory.warnings) ? strategyMemory.warnings.length : 0
3926
+ };
3927
+ }
3928
+ function summarizeCampaignBuilderProofDryRun(dryRunResult) {
3929
+ return {
3930
+ dryRun: dryRunResult.dryRun ?? dryRunResult.dry_run ?? null,
3931
+ status: dryRunResult.status ?? null,
3932
+ currentPhase: dryRunResult.currentPhase ?? dryRunResult.current_phase ?? null,
3933
+ campaignBuildId: dryRunResult.campaignBuildId ?? dryRunResult.campaign_build_id ?? null,
3934
+ plannedTargetCount: dryRunResult.plannedTargetCount ?? dryRunResult.planned_target_count ?? null
3935
+ };
3936
+ }
3937
+ function firstNonEmptyString(...values) {
3938
+ for (const value of values) {
3939
+ if (typeof value === "string" && value.trim()) return value;
3940
+ }
3941
+ return null;
3942
+ }
3594
3943
  function diagnosticMessages2(value) {
3595
3944
  if (!Array.isArray(value)) return [];
3596
3945
  return value.map((item) => {
@@ -6600,7 +6949,7 @@ async function main() {
6600
6949
  printHelp();
6601
6950
  return;
6602
6951
  }
6603
- const offlineCampaignAgentTemplate = (command === "campaign-agent" || command === "campaign-builder") && ["init", "template", "request-template", "new"].includes(String(process.argv[3] || ""));
6952
+ const offlineCampaignAgentTemplate = (command === "campaign-agent" || command === "campaign-builder") && ["init", "template", "request-template", "new", "kit", "build-kit", "blueprint"].includes(String(process.argv[3] || ""));
6604
6953
  if (!apiKey && !offlineCampaignAgentTemplate) {
6605
6954
  console.error("\u274C SIGNALIZ_API_KEY environment variable is required.");
6606
6955
  console.error(" Set it with: export SIGNALIZ_API_KEY=sk_...");
@@ -6964,6 +7313,38 @@ async function handleCampaignAgentCommand(signaliz, argv) {
6964
7313
  }
6965
7314
  return;
6966
7315
  }
7316
+ if (["kit", "build-kit", "blueprint"].includes(subcommand)) {
7317
+ const flags2 = parseFlags(argv.slice(1));
7318
+ const requestFromFile2 = campaignAgentRequestFileFromFlags(flags2);
7319
+ const fallbackGoal = stringFlag(flags2, "goal", "brief") || stringOrUndefined(requestFromFile2?.goal) || "Build a strategy-template campaign for mature operators in the target ICP.";
7320
+ const request2 = requestFromFile2 ? mergeCampaignAgentRequests(
7321
+ requestFromFile2,
7322
+ campaignAgentRequestFromFlags(fallbackGoal, flags2, { includeDefaults: false })
7323
+ ) : campaignAgentRequestTemplateFromFlags(flags2);
7324
+ const kit = createCampaignBuilderBuildKit({
7325
+ ...request2,
7326
+ includeLocalLeads: booleanFlag(flags2, "use-local-leads"),
7327
+ includeCustomToolPlaceholder: booleanFlag(flags2, "with-byo-placeholder") || booleanFlag(flags2, "include-custom-tool-placeholder") || booleanFlag(flags2, "include-byo-placeholder"),
7328
+ includeNango: !booleanFlag(flags2, "no-nango-catalog"),
7329
+ requestFile: stringFlag(flags2, "request-output-file", "request-file-name") || stringFlag(flags2, "request-file") || "campaign-request.json",
7330
+ cliPackage: stringFlag(flags2, "cli-package"),
7331
+ sdkPackage: stringFlag(flags2, "sdk-package")
7332
+ });
7333
+ const outputFile = stringFlag(flags2, "output-file", "kit-file", "out");
7334
+ if (outputFile) {
7335
+ (0, import_node_fs.writeFileSync)(outputFile, `${JSON.stringify(kit, null, 2)}
7336
+ `, "utf8");
7337
+ }
7338
+ if (booleanFlag(flags2, "json")) {
7339
+ printJson(kit);
7340
+ } else if (!outputFile) {
7341
+ printCampaignAgentBuildKit(kit);
7342
+ } else {
7343
+ console.log(`Campaign build kit written: ${outputFile}`);
7344
+ console.log(`Next: ${kit.cli_commands.find((command) => command.id === "proof_shortcut")?.command}`);
7345
+ }
7346
+ return;
7347
+ }
6967
7348
  if (["review", "status", "rows", "artifacts", "approve", "approve-delivery"].includes(subcommand)) {
6968
7349
  await handleCampaignAgentReviewCommand(signaliz, subcommand, argv.slice(1));
6969
7350
  return;
@@ -7011,12 +7392,11 @@ async function handleCampaignAgentCommand(signaliz, argv) {
7011
7392
  if (!readiness.summary.ready) process.exitCode = 1;
7012
7393
  return;
7013
7394
  }
7014
- const plan = await signaliz.campaignBuilderAgent.createPlan(request, planOptions);
7015
7395
  if (subcommand === "proof" || subcommand === "smoke") {
7016
- const result = await signaliz.campaignBuilderAgent.dryRunPlan(plan, {
7396
+ const proof = await signaliz.campaignBuilderAgent.proof(request, {
7397
+ ...planOptions,
7017
7398
  idempotencyKey: stringFlag(flags, "idempotency-key")
7018
7399
  });
7019
- const proof = createCampaignAgentProofReceipt(plan, result);
7020
7400
  if (booleanFlag(flags, "json")) {
7021
7401
  printJson(proof);
7022
7402
  } else {
@@ -7025,6 +7405,7 @@ async function handleCampaignAgentCommand(signaliz, argv) {
7025
7405
  if (!proof.success) process.exitCode = 1;
7026
7406
  return;
7027
7407
  }
7408
+ const plan = await signaliz.campaignBuilderAgent.createPlan(request, planOptions);
7028
7409
  if (isCommitPlan) {
7029
7410
  const result = await signaliz.campaignBuilderAgent.commitPlan(plan, {
7030
7411
  confirm: isConfirmedCommit,
@@ -7490,6 +7871,25 @@ function printCampaignAgentPlan(plan) {
7490
7871
  console.log(`- ${step.id}: ${step.tool}${step.approvalRequired ? " (approval required)" : ""}`);
7491
7872
  }
7492
7873
  }
7874
+ function printCampaignAgentBuildKit(kit) {
7875
+ console.log(`Campaign build kit: ${kit.strategy_template || "custom strategy"}`);
7876
+ console.log(`Request file: ${kit.request_file}`);
7877
+ console.log(`Built-ins: ${kit.built_in_lanes.join(", ") || "none"}`);
7878
+ console.log(`Playbooks: ${kit.operating_playbooks.join(", ") || "none"}`);
7879
+ console.log(`BYO routes: ${kit.custom_routes.length}`);
7880
+ console.log("\nCLI:");
7881
+ for (const command of kit.cli_commands.slice(0, 4)) {
7882
+ console.log(`- ${command.label}: ${command.command}`);
7883
+ }
7884
+ console.log("\nMCP:");
7885
+ for (const call of kit.mcp_calls.slice(0, 3)) {
7886
+ console.log(`- ${call.tool}: ${call.safety}`);
7887
+ }
7888
+ console.log("\nBYO tool pattern:");
7889
+ console.log(`- ${kit.byo_tool_pattern.cli_flag}`);
7890
+ console.log("\nNext:");
7891
+ for (const action of kit.next_actions.slice(0, 4)) console.log(`- ${action}`);
7892
+ }
7493
7893
  function printCampaignAgentExecution(payload, flags) {
7494
7894
  if (booleanFlag(flags, "json")) {
7495
7895
  printJson(payload);
@@ -7616,138 +8016,6 @@ function printCampaignAgentRows(result) {
7616
8016
  function asRecord4(value) {
7617
8017
  return value && typeof value === "object" && !Array.isArray(value) ? value : {};
7618
8018
  }
7619
- function createCampaignAgentProofReceipt(plan, result) {
7620
- const strategyMemory = asRecord4(plan.strategyMemoryStatus);
7621
- const dryRunResult = asRecord4(result);
7622
- const memoryReady = plan.strategyMemoryStatus ? strategyMemory.ready !== false : false;
7623
- const dryRunCompleted = dryRunResult.dryRun === true || dryRunResult.dry_run === true || dryRunResult.status === "dry_run";
7624
- const noLaunch = dryRunCompleted && !dryRunResult.campaignBuildId && !dryRunResult.campaign_build_id;
7625
- const gates = [
7626
- {
7627
- id: "strategy_memory_ready",
7628
- passed: memoryReady,
7629
- ready: strategyMemory.ready ?? null,
7630
- blocker_count: Array.isArray(strategyMemory.blockers) ? strategyMemory.blockers.length : 0
7631
- },
7632
- {
7633
- id: "campaign_plan_ready",
7634
- passed: Boolean(plan.planId && plan.mcpFlow.length > 0),
7635
- plan_id: plan.planId,
7636
- flow_steps: plan.mcpFlow.length
7637
- },
7638
- {
7639
- id: "approval_gates_present",
7640
- passed: plan.approvals.length > 0,
7641
- approval_types: plan.approvals.map((approval) => approval.type)
7642
- },
7643
- {
7644
- id: "dry_run_completed",
7645
- passed: dryRunCompleted,
7646
- status: dryRunResult.status ?? null,
7647
- current_phase: dryRunResult.currentPhase ?? dryRunResult.current_phase ?? null
7648
- },
7649
- {
7650
- id: "no_spendful_launch",
7651
- passed: noLaunch,
7652
- campaign_build_id: dryRunResult.campaignBuildId ?? dryRunResult.campaign_build_id ?? null
7653
- }
7654
- ];
7655
- return {
7656
- receipt_version: "campaign-agent-proof.v1",
7657
- source: "signaliz campaign-agent proof",
7658
- success: gates.every((gate) => gate.passed),
7659
- safety: {
7660
- spendful_tools_called: false,
7661
- external_writes_called: false,
7662
- sender_loads_called: false,
7663
- email_sends_called: false,
7664
- dry_run_only: true
7665
- },
7666
- campaign: {
7667
- plan_id: plan.planId,
7668
- campaign_name: plan.campaignName,
7669
- strategy_template: campaignAgentStrategyTemplate(plan),
7670
- target_count: plan.targetCount,
7671
- estimated_credits: plan.estimatedCredits,
7672
- operating_playbooks: plan.operatingPlaybooks.map((playbook) => playbook.slug)
7673
- },
7674
- gates,
7675
- strategy_memory_status: summarizeCampaignAgentStrategyMemory(strategyMemory),
7676
- dry_run_result: summarizeCampaignAgentDryRun(dryRunResult),
7677
- recommended_next_actions: [
7678
- "Review the plan, approvals, and dry-run result.",
7679
- "Use campaign-agent commit-plan --confirm-write only after review.",
7680
- "Use campaign-agent build-approved only with --confirm-launch, approval identity, approval types, and spend limit.",
7681
- "When an approved build reaches pending_approval, review rows and approve delivery through the Campaigns SDK."
7682
- ]
7683
- };
7684
- }
7685
- function campaignAgentString(...values) {
7686
- for (const value of values) {
7687
- if (typeof value === "string" && value.trim()) return value;
7688
- }
7689
- return null;
7690
- }
7691
- function campaignAgentStrategyTemplate(plan) {
7692
- const buildRequest = asRecord4(plan.buildRequest);
7693
- const strategyMemory = asRecord4(plan.strategyMemoryStatus);
7694
- const statusTemplate = strategyMemory.strategy_template ?? strategyMemory.strategyTemplate;
7695
- const statusTemplateRecord = asRecord4(statusTemplate);
7696
- const flowTemplate = plan.mcpFlow.map((step) => asRecord4(step.arguments).strategy_template ?? asRecord4(step.arguments).strategyTemplate).find((value) => typeof value === "string" && value.trim());
7697
- return campaignAgentString(
7698
- buildRequest.strategyTemplate,
7699
- buildRequest.strategy_template,
7700
- statusTemplate,
7701
- statusTemplateRecord.slug,
7702
- statusTemplateRecord.id,
7703
- flowTemplate
7704
- );
7705
- }
7706
- function summarizeCampaignAgentStrategyMemory(strategyMemory) {
7707
- if (Object.keys(strategyMemory).length === 0) return { ready: false };
7708
- const template = strategyMemory.strategy_template ?? strategyMemory.strategyTemplate;
7709
- const templateRecord = asRecord4(template);
7710
- const coverage = asRecord4(strategyMemory.coverage);
7711
- const rawSourceGroups = Array.isArray(strategyMemory.source_groups) ? strategyMemory.source_groups : Array.isArray(strategyMemory.sourceGroups) ? strategyMemory.sourceGroups : [];
7712
- const sourceGroups = rawSourceGroups.map((group) => {
7713
- const sourceGroup = asRecord4(group);
7714
- return {
7715
- id: sourceGroup.id ?? null,
7716
- required: sourceGroup.required ?? null,
7717
- ready: sourceGroup.ready ?? null,
7718
- counts: asRecord4(sourceGroup.counts)
7719
- };
7720
- });
7721
- return {
7722
- ready: strategyMemory.ready ?? null,
7723
- read_only: strategyMemory.read_only ?? strategyMemory.readOnly ?? null,
7724
- source_tool: campaignAgentString(strategyMemory.source_tool, strategyMemory.sourceTool),
7725
- strategy_template: {
7726
- slug: campaignAgentString(template, templateRecord.slug, templateRecord.id),
7727
- label: campaignAgentString(templateRecord.label)
7728
- },
7729
- coverage: {
7730
- required_groups_ready: coverage.required_groups_ready ?? coverage.requiredGroupsReady ?? null,
7731
- required_groups_total: coverage.required_groups_total ?? coverage.requiredGroupsTotal ?? null,
7732
- source_groups_ready: coverage.source_groups_ready ?? coverage.sourceGroupsReady ?? null,
7733
- source_groups_total: coverage.source_groups_total ?? coverage.sourceGroupsTotal ?? null,
7734
- knowledge_docs: coverage.knowledge_docs ?? coverage.knowledgeDocs ?? null,
7735
- memories: coverage.memories ?? null
7736
- },
7737
- source_groups: sourceGroups,
7738
- blocker_count: Array.isArray(strategyMemory.blockers) ? strategyMemory.blockers.length : 0,
7739
- warning_count: Array.isArray(strategyMemory.warnings) ? strategyMemory.warnings.length : 0
7740
- };
7741
- }
7742
- function summarizeCampaignAgentDryRun(dryRunResult) {
7743
- return {
7744
- dryRun: dryRunResult.dryRun ?? dryRunResult.dry_run ?? null,
7745
- status: dryRunResult.status ?? null,
7746
- currentPhase: dryRunResult.currentPhase ?? dryRunResult.current_phase ?? null,
7747
- campaignBuildId: dryRunResult.campaignBuildId ?? dryRunResult.campaign_build_id ?? null,
7748
- plannedTargetCount: dryRunResult.plannedTargetCount ?? dryRunResult.planned_target_count ?? null
7749
- };
7750
- }
7751
8019
  function printCampaignAgentProof(proof) {
7752
8020
  console.log(`Campaign-agent proof: ${proof.success ? "passed" : "failed"}`);
7753
8021
  const campaign = asRecord4(proof.campaign);
@@ -7819,6 +8087,7 @@ function printCampaignAgentHelp() {
7819
8087
  Signaliz campaign-agent commands:
7820
8088
 
7821
8089
  signaliz campaign-agent init [--goal TEXT] [--strategy-template ID] [--target-count N] [--use-local-leads] [--with-byo-placeholder] [--output-file FILE] [--json]
8090
+ signaliz campaign-agent kit [--goal TEXT | --request-file FILE] [--strategy-template ID] [--target-count N] [--use-local-leads] [--custom-tool provider:layer:tool[:mcp]] [--output-file FILE] [--json]
7822
8091
  signaliz campaign-agent doctor [--goal TEXT | --request-file FILE] [--strategy-template ID] [--target-count N] [--builtins lead_generation,email_finding,email_verification,signals,local_leads] [--custom-tool provider:layer:tool[:mcp]] [--json]
7823
8092
  signaliz campaign-agent plan (--goal TEXT | --request-file FILE) [--campaign-name NAME] [--workspace-label NAME] [--strategy-template industrial-ot-resilience|non-medical-home-care|agency-founder-led|cloud-infrastructure-displacement] [--operating-playbooks proof-first-vertical-gate,signal-led-copy-approval] [--target-count N] [--icp JSON] [--builtins lead_generation,email_finding,email_verification,signals,local_leads] [--use-local-leads] [--custom-tool provider:layer:tool[:mcp]] [--preferred-providers signaliz_native,octave] [--partners clay,instantly,nango] [--no-strategy-memory] [--no-kernel-plan] [--no-delivery-risk] [--json]
7824
8093
  signaliz campaign-agent proof (--goal TEXT | --request-file FILE) [--strategy-template ID] [--target-count N] [--use-local-leads] [--custom-tool provider:layer:tool[:mcp]] [--idempotency-key KEY] [--json]
@@ -7831,7 +8100,7 @@ Signaliz campaign-agent commands:
7831
8100
  signaliz campaign-agent artifacts <campaign_build_id> [--json]
7832
8101
  signaliz campaign-agent approve <campaign_build_id> --destination-type json|csv|webhook [--destination-config JSON] [--json]
7833
8102
 
7834
- The init command emits a reusable JSON CampaignBuilderAgentRequest. Doctor returns a readiness packet for built-in lanes, BYO routes, Memory, Brain, Kernel planning, and approval gates. The plan command composes an approval-gated strategy-template MCP flow. Proof runs the same plan path plus build_campaign dry_run=true and returns a no-spend receipt. Use --request-file to load a reusable request, then override fields such as --target-count or --strategy-template from the command line. Use --strategy-template to merge a private-safe strategy pattern into the plan without exposing private account labels, and --operating-playbooks to add reusable build-loop gates such as proof-first vertical qualification, net-new suppression, cache-first inventory, and signal-led copy approval. Built-ins map to Signaliz-native tools: lead_generation -> generate_leads, local_leads -> generate_local_leads, email_finding -> find_and_verify_emails, email_verification -> verify_emails, signals -> enrich_company_signals. Add BYO tools with --custom-tool provider:layer:tool[:mcp] or key=value pairs such as provider=apollo,layer=source,tool=apollo_search,mcp=apollo. Use --no-strategy-patterns or --no-workflow-patterns to disable default private strategy memory hints. Commit-plan dry-runs by default and writes only with --confirm-write plus approval identity. Dry-run executes build_campaign with dry_run=true. Approved build requires explicit launch confirmation and approval metadata; add --commit-before-launch to persist the reviewed plan as a GTM campaign before launch, --wait to poll until completion or pending approval, and --approve-delivery to approve reviewed webhook delivery after pending_approval. Use review to inspect status, sampled rows, artifacts, and delivery-readiness gates before approving delivery or routing rows to external tools.
8103
+ The init command emits a reusable JSON CampaignBuilderAgentRequest. Kit emits the full build packet: request JSON, exact CLI commands, MCP calls, SDK example, approval boundaries, and BYO integration pattern. Doctor returns a readiness packet for built-in lanes, BYO routes, Memory, Brain, Kernel planning, and approval gates. The plan command composes an approval-gated strategy-template MCP flow. Proof runs the same plan path plus build_campaign dry_run=true and returns a no-spend receipt. Use --request-file to load a reusable request, then override fields such as --target-count or --strategy-template from the command line. Use --strategy-template to merge a private-safe strategy pattern into the plan without exposing private account labels, and --operating-playbooks to add reusable build-loop gates such as proof-first vertical qualification, net-new suppression, cache-first inventory, and signal-led copy approval. Built-ins map to Signaliz-native tools: lead_generation -> generate_leads, local_leads -> generate_local_leads, email_finding -> find_and_verify_emails, email_verification -> verify_emails, signals -> enrich_company_signals. Add BYO tools with --custom-tool provider:layer:tool[:mcp] or key=value pairs such as provider=apollo,layer=source,tool=apollo_search,mcp=apollo. Use --no-strategy-patterns or --no-workflow-patterns to disable default private strategy memory hints. Commit-plan dry-runs by default and writes only with --confirm-write plus approval identity. Dry-run executes build_campaign with dry_run=true. Approved build requires explicit launch confirmation and approval metadata; add --commit-before-launch to persist the reviewed plan as a GTM campaign before launch, --wait to poll until completion or pending approval, and --approve-delivery to approve reviewed webhook delivery after pending_approval. Use review to inspect status, sampled rows, artifacts, and delivery-readiness gates before approving delivery or routing rows to external tools.
7835
8104
  `);
7836
8105
  }
7837
8106
  main().catch((e) => {