@whisperr/wizard 0.1.3 → 0.1.4

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/index.js +58 -41
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -597,41 +597,53 @@ import { query } from "@anthropic-ai/claude-agent-sdk";
597
597
  // src/core/playbooks/shared-prompt.ts
598
598
  var BASE_WIZARD_PROMPT = `
599
599
  You are the Whisperr Wizard \u2014 an expert integration agent running INSIDE a
600
- customer's code repository. Your job: wire up the Whisperr SDK so the product
601
- sends the right events to Whisperr, then stop. Whisperr is a churn-prevention
602
- engine that needs identify() (who the user is) and track() (what they do).
600
+ customer's code repository.
603
601
 
604
- You are billed per step and the user is watching the clock. Work FAST and
605
- DECISIVELY. Most failures come from over-exploring \u2014 do not do that.
602
+ MISSION:
603
+ Whisperr predicts churn and fires retention interventions from product events.
604
+ Two things make that work: (1) identify() tying events to a real user, and
605
+ (2) track() events fired at the right moment WITH the properties that give them
606
+ meaning. A well-placed event carrying its real properties is gold; a bare or
607
+ mis-placed event is noise that corrupts the customer's churn data. Your mission:
608
+ wire up everything in the plan that genuinely exists in this app, and for each
609
+ event you place, capture the properties that are actually available right there
610
+ in the code. You will NOT find everything \u2014 some events live server-side or
611
+ aren't in this codebase at all. That is expected and fine. Get what is here, get
612
+ it right, report the rest. Know exactly what you're doing; never hunt blindly.
613
+
614
+ You are billed per step and the user is watching. Work FAST and DECISIVELY.
606
615
 
607
616
  EFFICIENCY \u2014 non-negotiable:
608
617
  - Use Grep and Glob to find code. Do NOT read whole files; read the smallest
609
618
  slice you need.
610
619
  - NEVER re-read a file you just edited. Trust your edit.
611
- - Do not run the app, build, or heavy test suites. At most one quick static
612
- check, and only if the SDK guide tells you to.
620
+ - Do not run the app, build, or the analyzer/test suites. The human reviews the
621
+ diff.
613
622
  - Make several related edits in a row before pausing to think.
614
623
 
615
624
  DECISIVENESS:
616
625
  - When you find the right spot, edit it and move on immediately.
617
- - If you cannot find a clear place for something within ~2 searches, STOP
618
- looking for it. Either drop a single-line \`// TODO(whisperr): track(...)\`
619
- if an obvious spot exists, or just note it as a follow-up. Do not keep hunting.
626
+ - If you can't find a clear place for something within ~2 searches, STOP looking.
627
+ Leave a one-line \`// TODO(whisperr): ...\` only if an obvious spot exists,
628
+ otherwise just note it as a follow-up. Do not keep hunting.
620
629
 
621
- SCOPE REALISM:
622
- - Not every event exists in THIS app. Many are server-side (billing webhooks,
623
- delivery callbacks) or simply absent. That is expected. Instrument what
624
- clearly exists on the client; list the rest as follow-ups. Do not treat a
625
- missing call site as a problem to solve.
630
+ PROPERTY CAPTURE (this is the craft):
631
+ - For each event you place, look at what's in scope AT THAT CALL SITE \u2014 function
632
+ arguments, the object/model/state you're inside, nearby local variables \u2014 and
633
+ populate every listed property you can source from those values.
634
+ - Omit a property only if it genuinely isn't available there. Do NOT fetch,
635
+ compute, or invent data to fill a property, and do NOT wander off to find it.
636
+ - If a property marked (required) can't be sourced at your chosen site, that's a
637
+ strong hint you've picked the wrong site \u2014 reconsider; if it's still the best
638
+ spot, add the track() call and note the missing property.
626
639
 
627
640
  CORRECTNESS:
628
641
  - Match the app's existing conventions (imports, state management, file layout).
629
642
  - Use the EXACT snake_case event names given. Never invent or rename events.
630
- - A wrongly-placed business event corrupts churn data \u2014 worse than a missing one.
631
- Only place an event where you are confident the user action truly happens.
643
+ - Only place an event where you're confident the user action truly happens.
632
644
 
633
- End every task with a short summary: what you changed, and any follow-ups the
634
- human should handle (events you intentionally skipped + why).
645
+ End every task with a short summary: what you changed, which events you wired
646
+ (and the properties you attached), and the follow-ups you intentionally left.
635
647
  `.trim();
636
648
  function renderIdentifyBrief(m) {
637
649
  const lines = [];
@@ -640,14 +652,14 @@ function renderIdentifyBrief(m) {
640
652
  lines.push(`Ingestion API key: ${m.ingestionApiKey}`);
641
653
  if (m.businessContext) {
642
654
  lines.push("");
643
- lines.push(`Context: ${m.businessContext}`);
655
+ lines.push(`Business context: ${m.businessContext}`);
644
656
  }
645
657
  lines.push("");
646
658
  lines.push("identify():");
647
659
  if (m.identify.traits?.length) {
648
- lines.push(" Send these traits when available:");
660
+ lines.push(" Send these traits when readily available:");
649
661
  for (const t of m.identify.traits) {
650
- lines.push(` - ${t.name}${t.description ? ` (${t.description})` : ""}`);
662
+ lines.push(` - ${t.name}${t.description ? ` \u2014 ${t.description}` : ""}`);
651
663
  }
652
664
  }
653
665
  if (m.identify.channels?.length) {
@@ -661,18 +673,25 @@ function renderEventsBrief(m) {
661
673
  (a, b) => (b.importance ?? 0) - (a.importance ?? 0)
662
674
  );
663
675
  const lines = [];
676
+ if (m.businessContext) {
677
+ lines.push(`Business context: ${m.businessContext}`);
678
+ lines.push("");
679
+ }
664
680
  lines.push(
665
- `${events.length} candidate events (highest-impact first). Emit each with its EXACT name via track('<event_type>', { ...properties }).`
681
+ `${events.length} candidate events (highest-impact first). For each: fire track('<event_type>', { ...properties }) at the real moment it happens, and attach every listed property you can source from values in scope there. Skip an event entirely if it has no clear client-side trigger.`
666
682
  );
667
- lines.push("");
668
683
  for (const e of events) {
669
- const drivers = e.interventions?.length ? ` \u2014 drives: ${e.interventions.map((i) => i.label ?? i.code).join(", ")}` : "";
670
- lines.push(`- ${e.eventType}${e.label ? ` (${e.label})` : ""}${drivers}`);
671
- if (e.description) lines.push(` ${e.description}`);
684
+ lines.push("");
685
+ const why = e.interventions?.length ? ` \xB7 drives: ${e.interventions.map((i) => i.label ?? i.code).join(", ")}` : "";
686
+ lines.push(`\u25A0 ${e.eventType}${e.label ? ` (${e.label})` : ""}${why}`);
687
+ if (e.description) lines.push(` ${e.description}`);
672
688
  if (e.properties?.length) {
673
- lines.push(
674
- ` properties: ${e.properties.map((p2) => p2.name).join(", ")}`
675
- );
689
+ lines.push(" properties to capture if available:");
690
+ for (const p2 of e.properties) {
691
+ const req = p2.required ? " (required)" : "";
692
+ const desc = p2.description ? ` \u2014 ${p2.description}` : "";
693
+ lines.push(` \xB7 ${p2.name}${req}${desc}`);
694
+ }
676
695
  }
677
696
  }
678
697
  return lines.join("\n");
@@ -724,17 +743,15 @@ ${core.summary}`);
724
743
  if (manifest.events.length > 0) {
725
744
  progress?.onPhase?.("Instrumenting your events");
726
745
  const eventsPrompt = [
727
- `The Whisperr ${playbook.target.displayName} SDK is already installed,`,
728
- "initialized, and identify() is wired. Now add track() calls for product",
729
- "events.",
746
+ `The Whisperr ${playbook.target.displayName} SDK is already installed and`,
747
+ "initialized, and identify() is wired. Now instrument the product events",
748
+ "below with track().",
730
749
  "",
731
- "How to work:",
732
- "- Go in the order listed (highest-impact first).",
733
- "- For each event, Grep for where that user action happens. If there is a",
734
- " clear client-side call site, add the track() call with the exact name.",
735
- " If not, SKIP it (most server-side events won't exist here) \u2014 do not hunt.",
736
- "- You have a limited number of steps; spend them placing events, not",
737
- " exploring. Stop once the events that clearly exist in this app are wired.",
750
+ "Work in importance order. Place each event at its real call site and",
751
+ "attach the properties you can source from what's in scope there (see the",
752
+ "property-capture rule in your instructions). Skip fast when an event has",
753
+ "no clear client-side trigger \u2014 spend steps placing events, not exploring.",
754
+ "Stop once the events that clearly exist in this app are wired.",
738
755
  "",
739
756
  "----- EVENTS -----",
740
757
  renderEventsBrief(manifest),
@@ -1209,7 +1226,7 @@ async function main() {
1209
1226
  return;
1210
1227
  }
1211
1228
  if ("version" in parsed) {
1212
- console.log("0.1.3");
1229
+ console.log("0.1.4");
1213
1230
  return;
1214
1231
  }
1215
1232
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@whisperr/wizard",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "Whisperr Wizard — one command to integrate the Whisperr SDK into your app. Authenticates with your onboarded account and uses an AI coding agent to wire up identify() and your business events automatically.",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,