@signaliz/cli 1.0.18 → 1.0.19

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.
Files changed (2) hide show
  1. package/dist/bin.js +364 -14
  2. package/package.json +1 -1
package/dist/bin.js CHANGED
@@ -100,7 +100,7 @@ function normalizeCampaignBuildInput(raw) {
100
100
  return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
101
101
  };
102
102
  const policy = nested("policy", "policy");
103
- const signals = nested("signals", "signals");
103
+ const signals2 = nested("signals", "signals");
104
104
  const copy = nested("copy", "copy");
105
105
  const delivery = nested("delivery", "delivery");
106
106
  const learningHoldout = nested("learning_holdout", "learningHoldout");
@@ -131,11 +131,11 @@ function normalizeCampaignBuildInput(raw) {
131
131
  maxCredits: policy.max_credits ?? policy.maxCredits,
132
132
  verifyEmails: policy.verify_emails ?? policy.verifyEmails
133
133
  } : void 0,
134
- signals: signals ? {
135
- ...signals,
136
- customPrompt: signals.custom_prompt ?? signals.customPrompt,
137
- confidenceThreshold: signals.confidence_threshold ?? signals.confidenceThreshold,
138
- lookbackDays: signals.lookback_days ?? signals.lookbackDays
134
+ signals: signals2 ? {
135
+ ...signals2,
136
+ customPrompt: signals2.custom_prompt ?? signals2.customPrompt,
137
+ confidenceThreshold: signals2.confidence_threshold ?? signals2.confidenceThreshold,
138
+ lookbackDays: signals2.lookback_days ?? signals2.lookbackDays
139
139
  } : void 0,
140
140
  qualification: nested("qualification", "qualification"),
141
141
  copy: copy ? {
@@ -431,6 +431,69 @@ function parseJsonObjectFromString(value, label) {
431
431
  }
432
432
  return parsed;
433
433
  }
434
+ var PUBLIC_GROUND_TRUTH_CLI_FILTERS = [
435
+ ["industry", "industry"],
436
+ ["location", "location"],
437
+ ["nativeId", "native-id", "nativeId"],
438
+ ["entityName", "entity-name", "entityName"],
439
+ ["domain", "domain"],
440
+ ["websiteUrl", "website-url", "websiteUrl"],
441
+ ["phone", "phone"],
442
+ ["email", "email"],
443
+ ["city", "city"],
444
+ ["state", "state"],
445
+ ["postalCode", "postal-code", "postalCode"],
446
+ ["country", "country"],
447
+ ["sourceUrl", "source-url", "sourceUrl"],
448
+ ["naics", "naics"],
449
+ ["industryCode", "industry-code", "industryCode"],
450
+ ["industryType", "industry-type", "industryType"],
451
+ ["year", "year"],
452
+ ["quarter", "quarter"],
453
+ ["areaFips", "area-fips", "areaFips"],
454
+ ["geoId", "geo-id", "geoId"],
455
+ ["ownCode", "own-code", "ownCode"],
456
+ ["sourceUpdatedAfter", "source-updated-after", "sourceUpdatedAfter"],
457
+ ["sourceUpdatedBefore", "source-updated-before", "sourceUpdatedBefore"],
458
+ ["observedAfter", "observed-after", "observedAfter"],
459
+ ["observedBefore", "observed-before", "observedBefore"]
460
+ ];
461
+ function commandObjectFromKeyValueFlags(flags, keyValueNames, jsonNames) {
462
+ const object = {};
463
+ for (const jsonName of jsonNames) {
464
+ const parsed = commandJsonObjectFlag(flags, jsonName);
465
+ if (parsed) Object.assign(object, parsed);
466
+ }
467
+ for (const pair of repeatedCommandStringFlag(flags, ...keyValueNames)) {
468
+ const eq = pair.indexOf("=");
469
+ if (eq <= 0) die(`Expected key=value for --${keyValueNames[0]}`);
470
+ const key = pair.slice(0, eq).trim();
471
+ const value = pair.slice(eq + 1).trim();
472
+ if (!key) die(`Expected non-empty key for --${keyValueNames[0]}`);
473
+ object[key] = value;
474
+ }
475
+ return Object.keys(object).length > 0 ? object : void 0;
476
+ }
477
+ function publicGroundTruthFiltersFromCommandFlags(flags) {
478
+ const filters = {};
479
+ for (const [paramName, ...flagNames] of PUBLIC_GROUND_TRUTH_CLI_FILTERS) {
480
+ const value = commandStringFlag(flags, ...flagNames);
481
+ if (value) filters[paramName] = value;
482
+ }
483
+ const joinKeys = commandObjectFromKeyValueFlags(
484
+ flags,
485
+ ["join-key", "joinKey"],
486
+ ["join-keys-json", "joinKeysJson"]
487
+ );
488
+ const rowData = commandObjectFromKeyValueFlags(
489
+ flags,
490
+ ["row-data", "rowData"],
491
+ ["row-data-json", "rowDataJson"]
492
+ );
493
+ if (joinKeys) filters.joinKeys = joinKeys;
494
+ if (rowData) filters.rowData = rowData;
495
+ return filters;
496
+ }
434
497
  function output(data, humanFn) {
435
498
  if (jsonMode()) {
436
499
  console.log(JSON.stringify(data, null, 2));
@@ -608,6 +671,7 @@ function inferMcpToolCategory(toolName) {
608
671
  }
609
672
  if (toolName.includes("icp")) return "icp";
610
673
  if (toolName.startsWith("ai_clean_")) return "data_cleaning";
674
+ if (toolName.includes("public_ground_truth")) return "public_data";
611
675
  if (toolName.includes("system") || toolName.includes("workflow")) return "automation";
612
676
  if (toolName.includes("agent") || toolName.includes("platform_health") || toolName === "discover_capabilities") return "observability";
613
677
  return void 0;
@@ -1097,6 +1161,10 @@ Discovery:
1097
1161
  --category NAME Filter by category
1098
1162
  discover --query "..." Find relevant MCP tools/capabilities
1099
1163
  --category NAME Optional category filter, e.g. ops or enrichment
1164
+ public-data search Search public registry/cache records
1165
+ --query "..." Company/name/domain/native ID search text
1166
+ --source-id ID Optional source filter
1167
+ public-data sources List public data source IDs and join-key metadata
1100
1168
 
1101
1169
  AI:
1102
1170
  ai multi-model Run Custom AI Enrichment - Multi Model
@@ -1113,6 +1181,22 @@ AI:
1113
1181
  Record fields containing attachment URLs/arrays
1114
1182
  --max-concurrency N Record concurrency, default 3, maximum 5
1115
1183
  --confirm-spend Required to run spendful AI enrichment
1184
+ ai fusion Run AI Enrichment Fusion with OpenRouter Fusion
1185
+ --prompt "..." Prompt/template for each record (required)
1186
+ --preset general-budget|general-high
1187
+ --records-file FILE JSON array, or object with records/inputs/data
1188
+ --output-fields a:text,b:number
1189
+ --dry-run Default. Return a no-spend Fusion plan
1190
+ --confirm-spend Run a live experimental probe with dry_run=false
1191
+
1192
+ Signals:
1193
+ signals enrich Run canonical web-grounded company signal enrichment (up to 15 signals)
1194
+ signals fusion Run Signal Fusion for company signal intelligence
1195
+ --domain example.com Company domain, or use --company-name
1196
+ --preset general-budget|general-high
1197
+ --signal-types hiring,funding
1198
+ --dry-run Default. Return a no-spend Fusion plan
1199
+ --confirm-spend Run a live experimental probe with dry_run=false
1116
1200
 
1117
1201
  Lead Generation:
1118
1202
  lead generate Start a B2B lead-generation job
@@ -2717,6 +2801,111 @@ async function discover(rest) {
2717
2801
  }
2718
2802
  );
2719
2803
  }
2804
+ function publicDataPositionalText(rest) {
2805
+ const parts = [];
2806
+ for (let i = 0; i < rest.length; i += 1) {
2807
+ const part = rest[i];
2808
+ if (part.startsWith("--")) {
2809
+ if (!part.includes("=") && rest[i + 1] && !rest[i + 1].startsWith("--")) i += 1;
2810
+ continue;
2811
+ }
2812
+ parts.push(part);
2813
+ }
2814
+ return parts.join(" ").trim() || void 0;
2815
+ }
2816
+ function publicDataCell(value, width) {
2817
+ const text = String(value ?? "").replace(/\s+/g, " ").trim();
2818
+ return text.length > width ? `${text.slice(0, Math.max(width - 3, 0))}...` : text;
2819
+ }
2820
+ function printPublicDataSearchResult(result) {
2821
+ const records = Array.isArray(result.records) ? result.records : [];
2822
+ console.log(`Public data search: ${result.total_count ?? 0} matches (${records.length} returned)`);
2823
+ if (result.query) console.log(`Query: ${result.query}`);
2824
+ if (result.source_id) console.log(`Source: ${result.source_id}`);
2825
+ if (result.entity_type) console.log(`Entity type: ${result.entity_type}`);
2826
+ if (!records.length) {
2827
+ console.log("No records matched.");
2828
+ return;
2829
+ }
2830
+ console.log("");
2831
+ console.log("Source".padEnd(22) + "Native ID".padEnd(22) + "Name".padEnd(42) + "Industry".padEnd(28) + "Domain".padEnd(24) + "Loc".padEnd(12) + "Match");
2832
+ console.log("-".repeat(160));
2833
+ for (const record2 of records) {
2834
+ const loc = [record2.city, record2.state].filter(Boolean).join(", ");
2835
+ const industry = [record2.industry_code, record2.industry_name].filter(Boolean).join(" ");
2836
+ console.log(
2837
+ publicDataCell(record2.source_id, 21).padEnd(22) + publicDataCell(record2.native_id, 21).padEnd(22) + publicDataCell(record2.entity_name, 41).padEnd(42) + publicDataCell(industry, 27).padEnd(28) + publicDataCell(record2.domain, 23).padEnd(24) + publicDataCell(loc, 11).padEnd(12) + publicDataCell(record2.match_type, 16)
2838
+ );
2839
+ }
2840
+ if (result.next_offset !== null && result.next_offset !== void 0) {
2841
+ console.log(`
2842
+ Next page: --offset ${result.next_offset}`);
2843
+ }
2844
+ }
2845
+ function printPublicDataSources(result) {
2846
+ const sources = Array.isArray(result.sources) ? result.sources : [];
2847
+ console.log(`Public data sources: ${sources.length}/${result.total ?? sources.length}`);
2848
+ if (!sources.length) {
2849
+ console.log("No sources matched.");
2850
+ return;
2851
+ }
2852
+ console.log("");
2853
+ console.log("Source ID".padEnd(30) + "Status".padEnd(12) + "Rung".padEnd(7) + "Join key".padEnd(20) + "Cadence".padEnd(16) + "Name");
2854
+ console.log("-".repeat(120));
2855
+ for (const source of sources) {
2856
+ console.log(
2857
+ publicDataCell(source.id, 29).padEnd(30) + publicDataCell(source.ingestion_status, 11).padEnd(12) + String(source.ground_truth_rung ?? "").padEnd(7) + publicDataCell(source.primary_join_key || source.join_key_quality, 19).padEnd(20) + publicDataCell(source.update_cadence, 15).padEnd(16) + publicDataCell(source.name, 40)
2858
+ );
2859
+ }
2860
+ }
2861
+ async function publicData(sub, rest) {
2862
+ if (!sub || sub === "--help" || sub === "-h" || sub === "help") {
2863
+ process.stdout.write(`signaliz public-data <search|sources> [options]
2864
+
2865
+ Search the public-ground-truth cache of public registry and disclosure data.
2866
+
2867
+ Examples:
2868
+ signaliz public-data search --query "swift transportation" --source-id fmcsa_company_census --limit 10
2869
+ signaliz public-data search --industry "software publishers" --location CA --limit 25 --json
2870
+ signaliz public-data search --source-id bls_qcew --naics 541511 --state CA --year 2025 --json
2871
+ signaliz public-data search --domain swifttrans.com --json
2872
+ signaliz public-data search --join-key ein=123456789 --json
2873
+ signaliz public-data sources --status ready --json
2874
+ `);
2875
+ return;
2876
+ }
2877
+ const sdk = getSdk();
2878
+ if (!sdk.publicGroundTruth?.search || !sdk.publicGroundTruth?.listSources) {
2879
+ die("Installed @signaliz/sdk does not expose publicGroundTruth yet. Rebuild or upgrade @signaliz/sdk.");
2880
+ }
2881
+ if (sub === "sources" || sub === "list-sources") {
2882
+ const flags2 = parseCommandFlags(rest);
2883
+ const result2 = await sdk.publicGroundTruth.listSources({
2884
+ query: commandStringFlag(flags2, "query", "q", "search"),
2885
+ status: commandStringFlag(flags2, "status"),
2886
+ limit: commandNumberFlag(flags2, "limit")
2887
+ });
2888
+ return output(result2, () => printPublicDataSources(result2));
2889
+ }
2890
+ if (sub !== "search") die("Usage: signaliz public-data <search|sources>");
2891
+ const flags = parseCommandFlags(rest);
2892
+ const query = commandStringFlag(flags, "query", "q", "search") || publicDataPositionalText(rest);
2893
+ const sourceId = commandStringFlag(flags, "source-id", "sourceId");
2894
+ const entityType = commandStringFlag(flags, "entity-type", "entityType");
2895
+ const filters = publicGroundTruthFiltersFromCommandFlags(flags);
2896
+ if (!query && !sourceId && !entityType && Object.keys(filters).length === 0) {
2897
+ die("Usage: signaliz public-data search [--query TEXT] [--industry TEXT] [--location TEXT] [--domain DOMAIN] [--naics CODE] [--join-key k=v]");
2898
+ }
2899
+ const result = await sdk.publicGroundTruth.search({
2900
+ query,
2901
+ sourceId,
2902
+ entityType,
2903
+ ...filters,
2904
+ limit: commandNumberFlag(flags, "limit"),
2905
+ offset: commandNumberFlag(flags, "offset")
2906
+ });
2907
+ return output(result, () => printPublicDataSearchResult(result));
2908
+ }
2720
2909
  function normalizeAiRecords(value, source) {
2721
2910
  if (Array.isArray(value)) {
2722
2911
  if (value.every((item) => item && typeof item === "object" && !Array.isArray(item))) {
@@ -2802,12 +2991,47 @@ function aiAttachmentsFromFlags() {
2802
2991
  return attachments;
2803
2992
  }
2804
2993
  async function ai(sub, rest) {
2805
- if (sub !== "multi-model" && sub !== "multimodel") {
2806
- die('Usage: signaliz ai multi-model --prompt "..." --confirm-spend');
2807
- }
2808
2994
  if (flagArg("model") !== void 0 || hasFlag("model") || flagArg("analysis-models") !== void 0 || hasFlag("analysis-models") || flagArg("judge-model") !== void 0 || hasFlag("judge-model")) {
2809
2995
  die("Custom AI model selection is no longer supported. Signaliz-hosted custom AI uses the default model and returns model readback metadata.");
2810
2996
  }
2997
+ if (sub === "fusion") {
2998
+ const promptText2 = promptArg(rest);
2999
+ if (!promptText2) die('Usage: signaliz ai fusion --prompt "..." [--dry-run|--confirm-spend]');
3000
+ const dryRun = hasFlag("dry-run") || !hasFlag("confirm-spend");
3001
+ const sdk2 = getSdk();
3002
+ const result2 = await sdk2.ai.fusion({
3003
+ prompt: promptText2,
3004
+ records: aiRecordsFromFlags(),
3005
+ preset: flagArg("preset") || "general-budget",
3006
+ systemPrompt: flagArg("system-prompt"),
3007
+ temperature: numberFlag("temperature"),
3008
+ maxToolCalls: numberFlag("max-tool-calls"),
3009
+ maxTokens: numberFlag("max-tokens"),
3010
+ timeoutMs: numberFlag("timeout-ms"),
3011
+ dryRun,
3012
+ confirmSpend: !dryRun,
3013
+ maxCredits: numberFlag("max-credits"),
3014
+ maxCostUsd: numberFlag("max-cost-usd"),
3015
+ outputFields: aiOutputFieldsFromFlags()
3016
+ });
3017
+ return output(result2, () => {
3018
+ console.log(dryRun || result2.raw?.dry_run ? "AI Enrichment Fusion dry run" : "AI Enrichment Fusion complete");
3019
+ console.log(` Model: ${result2.model || "openrouter/fusion"}`);
3020
+ console.log(` Preset: ${String(result2.fusion?.preset || flagArg("preset") || "general-budget")}`);
3021
+ console.log(` Records: ${result2.results.length}`);
3022
+ console.log(` Cost USD: $${Number(result2.costUsd || 0).toFixed(6)}`);
3023
+ console.log(` Credits: ${result2.creditsUsed}`);
3024
+ console.log(` Tokens: ${result2.tokensUsed}`);
3025
+ const preview = result2.results.slice(0, 3);
3026
+ if (preview.length) {
3027
+ console.log("\nResults preview:");
3028
+ console.log(JSON.stringify(preview, null, 2));
3029
+ }
3030
+ });
3031
+ }
3032
+ if (sub !== "multi-model" && sub !== "multimodel") {
3033
+ die('Usage: signaliz ai <multi-model|fusion> --prompt "..." --confirm-spend');
3034
+ }
2811
3035
  const promptText = promptArg(rest);
2812
3036
  if (!promptText) die('Usage: signaliz ai multi-model --prompt "..." --confirm-spend');
2813
3037
  if (!hasFlag("confirm-spend")) {
@@ -2844,6 +3068,118 @@ async function ai(sub, rest) {
2844
3068
  }
2845
3069
  });
2846
3070
  }
3071
+ function signalCompaniesFromFlags() {
3072
+ const companiesFile = flagArg("companies-file");
3073
+ if (companiesFile) return normalizeAiRecords(readJsonValue(companiesFile), companiesFile);
3074
+ const companiesJson = flagArg("companies-json");
3075
+ if (companiesJson) return normalizeAiRecords(JSON.parse(companiesJson), "--companies-json");
3076
+ return void 0;
3077
+ }
3078
+ async function signals(sub, rest) {
3079
+ if (sub === "enrich") {
3080
+ const domain2 = flagArg("domain") || flagArg("company-domain");
3081
+ const companyName2 = flagArg("company-name") || rest.find((item) => !item.startsWith("--"));
3082
+ if (!domain2 && !companyName2) {
3083
+ die("Usage: signaliz signals enrich --domain example.com [--target-signal-count 15]");
3084
+ }
3085
+ const sdk2 = getSdk();
3086
+ const result2 = await sdk2.signals.enrichV2({
3087
+ domain: domain2,
3088
+ companyName: companyName2,
3089
+ researchPrompt: flagArg("prompt") || flagArg("research-prompt"),
3090
+ signalTypes: csvFlag("signal-types") || ["all"],
3091
+ targetSignalCount: numberFlag("target-signal-count"),
3092
+ lookbackDays: numberFlag("lookback-days"),
3093
+ online: !hasFlag("offline"),
3094
+ enableDeepSearch: !hasFlag("shallow") && !hasFlag("offline"),
3095
+ skipCache: hasFlag("skip-cache") || hasFlag("fresh-only")
3096
+ });
3097
+ return output(result2, () => {
3098
+ console.log("Company signal enrichment complete");
3099
+ console.log(` Company: ${result2.company.name || companyName2 || domain2}`);
3100
+ console.log(` Signals: ${result2.signalCount}`);
3101
+ const preview = result2.signals.slice(0, 5);
3102
+ if (preview.length) {
3103
+ console.log("\nPreview:");
3104
+ console.log(JSON.stringify(preview, null, 2));
3105
+ }
3106
+ });
3107
+ }
3108
+ if (sub === "signal-to-copy" || sub === "personalize") {
3109
+ const companyDomain = flagArg("company-domain") || flagArg("domain");
3110
+ const personName = flagArg("person-name") || flagArg("name");
3111
+ const title = flagArg("title");
3112
+ const campaignOffer = flagArg("campaign-offer") || flagArg("offer");
3113
+ if (!companyDomain || !personName || !title || !campaignOffer) {
3114
+ die('Usage: signaliz signals signal-to-copy --company-domain example.com --person-name "Alex Smith" --title "VP Sales" --campaign-offer "sales intelligence platform" [--research-prompt "..."]');
3115
+ }
3116
+ const result2 = await getSdk().signals.signalToCopy({
3117
+ companyDomain,
3118
+ personName,
3119
+ title,
3120
+ campaignOffer,
3121
+ researchPrompt: flagArg("research-prompt") || flagArg("prompt")
3122
+ });
3123
+ return output(result2, () => {
3124
+ console.log(`Signal Copy: ${result2.strongestSignal}`);
3125
+ console.log(`Confidence: ${result2.confidence}`);
3126
+ console.log(`Evidence: ${result2.evidenceUrl}`);
3127
+ for (const variation of result2.variations) {
3128
+ console.log(`
3129
+ === ${variation.style} ===`);
3130
+ console.log(`Subject: ${variation.subjectLine}`);
3131
+ console.log(variation.email || `${variation.openingLine}
3132
+
3133
+ ${variation.cta}`);
3134
+ }
3135
+ });
3136
+ }
3137
+ if (sub !== "fusion") {
3138
+ die("Usage: signaliz signals <enrich|signal-to-copy|fusion> --domain example.com");
3139
+ }
3140
+ const dryRun = hasFlag("dry-run") || !hasFlag("confirm-spend");
3141
+ const companies = signalCompaniesFromFlags();
3142
+ const domain = flagArg("domain") || flagArg("company-domain");
3143
+ const companyName = flagArg("company-name") || rest.find((item) => !item.startsWith("--"));
3144
+ const linkedinUrl = flagArg("linkedin-url");
3145
+ if (!companies?.length && !domain && !companyName && !linkedinUrl) {
3146
+ die("Usage: signaliz signals fusion --domain example.com [--dry-run|--confirm-spend]");
3147
+ }
3148
+ const sdk = getSdk();
3149
+ const result = await sdk.signals.fusion({
3150
+ companies,
3151
+ domain,
3152
+ companyName,
3153
+ linkedinUrl,
3154
+ preset: flagArg("preset") || "general-budget",
3155
+ researchPrompt: flagArg("prompt") || flagArg("research-prompt"),
3156
+ signalTypes: csvFlag("signal-types"),
3157
+ lookbackDays: numberFlag("lookback-days"),
3158
+ targetSignalCount: numberFlag("target-signal-count"),
3159
+ maxToolCalls: numberFlag("max-tool-calls"),
3160
+ maxTokens: numberFlag("max-tokens"),
3161
+ timeoutMs: numberFlag("timeout-ms"),
3162
+ dryRun,
3163
+ confirmSpend: !dryRun,
3164
+ maxCredits: numberFlag("max-credits"),
3165
+ maxCostUsd: numberFlag("max-cost-usd")
3166
+ });
3167
+ return output(result, () => {
3168
+ console.log(dryRun || result.raw?.dry_run ? "Signal Fusion dry run" : "Signal Fusion complete");
3169
+ console.log(` Model: ${result.model || "openrouter/fusion"}`);
3170
+ console.log(` Preset: ${String(result.fusion?.preset || flagArg("preset") || "general-budget")}`);
3171
+ console.log(` Companies: ${result.results.length || 1}`);
3172
+ console.log(` Signals: ${result.signalCount}`);
3173
+ console.log(` Cost USD: $${Number(result.costUsd || 0).toFixed(6)}`);
3174
+ console.log(` Credits: ${result.creditsUsed}`);
3175
+ console.log(` Tokens: ${result.tokensUsed}`);
3176
+ const preview = result.signals.length ? result.signals.slice(0, 5) : result.results.slice(0, 3);
3177
+ if (preview.length) {
3178
+ console.log("\nPreview:");
3179
+ console.log(JSON.stringify(preview, null, 2));
3180
+ }
3181
+ });
3182
+ }
2847
3183
  async function campaignBuild() {
2848
3184
  if (isHelpRequest(process.argv.slice(4))) {
2849
3185
  process.stdout.write(campaignHelpFor("build"));
@@ -3093,7 +3429,10 @@ function printCampaignCustomerRowCounts(status) {
3093
3429
  if (!counts || typeof counts !== "object") return;
3094
3430
  const value = (camel, snake) => counts[camel] ?? counts[snake] ?? "n/a";
3095
3431
  const requested = value("requestedTarget", "requested_target");
3096
- console.log(`Customer rows: accepted ${value("acceptedRows", "accepted_rows")}/${requested}, copied ${value("copiedRows", "copied_rows")}, approval-ready ${value("approvalReadyRows", "approval_ready_rows")}, QA-ready ${value("qaReadyRows", "qa_ready_rows")}, delivered ${value("deliveredRows", "delivered_rows")}`);
3432
+ const copied = value("copiedRows", "copied_rows");
3433
+ const copySkipped = value("copySkippedRows", "copy_skipped_rows");
3434
+ const copyLabel = typeof copySkipped === "number" && copySkipped > 0 && (!copied || copied === "n/a") ? `copy-skipped ${copySkipped}` : `copied ${copied}`;
3435
+ console.log(`Customer rows: accepted ${value("acceptedRows", "accepted_rows")}/${requested}, ${copyLabel}, approval-ready ${value("approvalReadyRows", "approval_ready_rows")}, QA-ready ${value("qaReadyRows", "qa_ready_rows")}, delivered ${value("deliveredRows", "delivered_rows")}`);
3097
3436
  const shortfalls = [
3098
3437
  ["accepted", value("acceptedShortfall", "accepted_shortfall")],
3099
3438
  ["usable", value("usableShortfall", "usable_shortfall")],
@@ -3211,7 +3550,11 @@ function formatCampaignRowsForOperator(rows) {
3211
3550
  disqualifiers: firstArray(data.disqualifiers),
3212
3551
  signal: data.signal_title ? {
3213
3552
  type: data.signal_type || null,
3553
+ family: data.signal_family || data.signal_type || null,
3214
3554
  title: data.signal_title,
3555
+ source_type: data.signal_source_type || data.signal_event_label || data.signal_classification?.label || null,
3556
+ source_provenance: data.signal_source_provenance || data.source_provenance || null,
3557
+ classification: data.signal_classification || null,
3215
3558
  summary: data.signal_summary || null,
3216
3559
  date: data.signal_date || null,
3217
3560
  confidence: data.signal_confidence ?? null,
@@ -3353,10 +3696,10 @@ var CAMPAIGN_AGENT_APPROVAL_TYPES = [
3353
3696
  "launch"
3354
3697
  ];
3355
3698
  var CAMPAIGN_AGENT_TEMPLATE_PLAYBOOKS = {
3356
- "industrial-ot-resilience": ["net-new-suppressed-list", "proof-first-vertical-gate", "signal-led-copy-approval"],
3357
- "non-medical-home-care": ["proof-first-vertical-gate", "domain-first-recovery", "table-workflow-handoff"],
3358
- "agency-founder-led": ["net-new-suppressed-list", "signal-led-copy-approval", "table-workflow-handoff"],
3359
- "cloud-infrastructure-displacement": ["proof-first-vertical-gate", "domain-first-recovery", "signal-led-copy-approval"]
3699
+ "industrial-ot-resilience": ["net-new-suppressed-list", "proof-first-vertical-gate", "signal-led-copy-approval", "icp-persona-segmentation", "buying-signal-prioritization", "multi-channel-sequence-fit", "revops-feedback-loop"],
3700
+ "non-medical-home-care": ["proof-first-vertical-gate", "domain-first-recovery", "table-workflow-handoff", "icp-persona-segmentation", "buying-signal-prioritization", "multi-channel-sequence-fit", "revops-feedback-loop"],
3701
+ "agency-founder-led": ["net-new-suppressed-list", "signal-led-copy-approval", "table-workflow-handoff", "icp-persona-segmentation", "buying-signal-prioritization", "multi-channel-sequence-fit", "revops-feedback-loop"],
3702
+ "cloud-infrastructure-displacement": ["proof-first-vertical-gate", "domain-first-recovery", "signal-led-copy-approval", "icp-persona-segmentation", "buying-signal-prioritization", "multi-channel-sequence-fit", "revops-feedback-loop"]
3360
3703
  };
3361
3704
  var CAMPAIGN_AGENT_HELP = `signaliz campaign-agent <command> [options]
3362
3705
 
@@ -7162,8 +7505,15 @@ async function main() {
7162
7505
  return tools();
7163
7506
  case "discover":
7164
7507
  return discover(rest);
7508
+ case "public-data":
7509
+ case "ground-truth":
7510
+ case "public-ground-truth":
7511
+ return publicData(rest[0], rest.slice(1));
7165
7512
  case "ai":
7166
7513
  return ai(rest[0], rest.slice(1));
7514
+ case "signal":
7515
+ case "signals":
7516
+ return signals(rest[0], rest.slice(1));
7167
7517
  case "lead":
7168
7518
  case "leads":
7169
7519
  return lead(rest[0], rest.slice(1));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@signaliz/cli",
3
- "version": "1.0.18",
3
+ "version": "1.0.19",
4
4
  "description": "Signaliz CLI — GTM Kernel, Nango routes, MCP, and enrichment operations.",
5
5
  "bin": {
6
6
  "signaliz": "dist/bin.js"