@sonnechasser/ntrp 2.3.2 → 2.4.1

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/index.js CHANGED
@@ -1584,7 +1584,7 @@ function printGuideCatalogLine(slide) {
1584
1584
  function printDeepdiveHint(metricId, label) {
1585
1585
  const name = label ?? metricId;
1586
1586
  console.log(
1587
- " " + chalk3.dim(`Ask what ${name.toLowerCase()} means \u2014 or `) + paint("accent", `/tour ${metricId}`) + chalk3.dim(" for the card")
1587
+ " " + chalk3.dim(`Ask what ${name.toLowerCase()} means \u2014 or `) + paint("accent", `/tour ${metricId}`) + chalk3.dim(" if you want the card.")
1588
1588
  );
1589
1589
  console.log();
1590
1590
  }
@@ -18358,7 +18358,24 @@ function listMetricExplainers(kind) {
18358
18358
  function getCoreDeckExplainers() {
18359
18359
  return CORE_DECK_IDS.map((id) => BY_ID.get(id)).filter(Boolean);
18360
18360
  }
18361
- var VITALS, SAAS, METRIC_DEFINITIONS, CORE_DECK_IDS, BY_ID, ALIAS_INDEX, SAAS_METRIC_IDS, GATING_LAYER_VISUAL;
18361
+ function buildVitalSignsPromptBlock() {
18362
+ return VITAL_IDS.map((id) => {
18363
+ const m = getMetricExplainer(id);
18364
+ if (!m) {
18365
+ throw new Error(`buildVitalSignsPromptBlock: missing explainer for ${id}`);
18366
+ }
18367
+ if (!m.dollar_label) {
18368
+ throw new Error(`buildVitalSignsPromptBlock: missing dollar_label for ${id}`);
18369
+ }
18370
+ return [
18371
+ `- ${m.id}: ${m.tagline}`,
18372
+ ` Teach: ${m.meaning}`,
18373
+ ` Expert read: ${m.expert_read}`,
18374
+ ` Dollar label: ${m.dollar_label}`
18375
+ ].join("\n");
18376
+ }).join("\n");
18377
+ }
18378
+ var VITALS, SAAS, METRIC_DEFINITIONS, CORE_DECK_IDS, BY_ID, ALIAS_INDEX, VITAL_IDS, SAAS_METRIC_IDS, GATING_LAYER_VISUAL;
18362
18379
  var init_metric_definitions = __esm({
18363
18380
  "src/data/metric-definitions.ts"() {
18364
18381
  "use strict";
@@ -19165,6 +19182,13 @@ var init_metric_definitions = __esm({
19165
19182
  idx.set("thread-depth", "thread_depth");
19166
19183
  return idx;
19167
19184
  })();
19185
+ VITAL_IDS = [
19186
+ "freshness",
19187
+ "flow_rate",
19188
+ "drop_rate",
19189
+ "signal_to_noise",
19190
+ "thread_depth"
19191
+ ];
19168
19192
  SAAS_METRIC_IDS = SAAS.map((m) => m.id);
19169
19193
  GATING_LAYER_VISUAL = {
19170
19194
  kind: "layer_stack",
@@ -25926,12 +25950,9 @@ var init_ghost_hints = __esm({
25926
25950
  init_suggested_asks();
25927
25951
  PHASE_GHOST_HINTS = {
25928
25952
  orient: [
25929
- 'try "pipeline health"',
25930
25953
  'try "how healthy is the pipeline?"',
25931
- 'try "what should I do next?"',
25932
- 'try "is our retention real for the board?"',
25933
- 'try "what is the most expensive problem to solve?"',
25934
- 'try "board deck on Q3"'
25954
+ 'try "what does freshness mean?"',
25955
+ 'try "what should I do next?"'
25935
25956
  ],
25936
25957
  awaiting_data: [
25937
25958
  'try "use demo data"',
@@ -36740,7 +36761,7 @@ async function handler19(args, ctx) {
36740
36761
  console.log(chalk51.dim(` Trigger: ${triggerLabel} \u2014 ${play.trigger_condition}`));
36741
36762
  if (play.trigger_vital_sign) {
36742
36763
  console.log(
36743
- chalk51.dim(" Ask what ") + chalk51.dim(play.trigger_vital_sign.replace(/_/g, " ")) + chalk51.dim(" means \u2014 or ") + paint("accent", `/tour ${play.trigger_vital_sign}`) + chalk51.dim(" for the card")
36764
+ chalk51.dim(" Ask what ") + chalk51.dim(play.trigger_vital_sign.replace(/_/g, " ")) + chalk51.dim(" means \u2014 or ") + paint("accent", `/tour ${play.trigger_vital_sign}`) + chalk51.dim(" if you want the card.")
36744
36765
  );
36745
36766
  }
36746
36767
  console.log();
@@ -40471,7 +40492,7 @@ function getDeepdiveNudge(ctx) {
40471
40492
  if (!hasAnalysisForDeepdiveNudge(ctx)) return null;
40472
40493
  return {
40473
40494
  text: "Ask how healthy the pipeline looks",
40474
- tip: "Or /tour for the numbers deck",
40495
+ tip: "We check if the number is real \u2014 then where deals stick, leak, or go thin. Two checks use our names. Or /tour if you want the deck.",
40475
40496
  command: "/tour"
40476
40497
  };
40477
40498
  }
@@ -40807,16 +40828,12 @@ var init_metric_tour = __esm({
40807
40828
  TOUR_SKIPPED_KEY = "metrics-tour-skipped";
40808
40829
  HOME_NUDGE_SEEN_KEY = "metrics-tour-home-nudge-seen";
40809
40830
  METRICS_TOUR_MILESTONE_ID = "metrics_tour";
40810
- TOUR_INTRO_TITLE = "How we listen to a pipeline";
40831
+ TOUR_INTRO_TITLE = "Are these pipeline numbers trustworthy \u2014 and where money leaks?";
40811
40832
  TOUR_CLOSE_TITLE = "Curious? Start listening";
40812
40833
  TOUR_INTRO_LINES = [
40813
- "We think about GTM health through two lenses \u2014 then we'll show how to talk to NTRP.",
40814
- "",
40815
- "SaaS metrics (next) \u2014 ARR, NRR, coverage, win rate, velocity. Boards already know these names; we'll walk how we derive them from CRM exports, and what we trust (or don't) when the data is messy.",
40816
- "",
40817
- "Vital signs (after) \u2014 Freshness, Flow Rate, Drop Rate, Signal:Noise, Thread Depth. These are our stethoscope: each score has a dollar translation, and we read them in layer order so an upstream red doesn't get papered over by a prettier downstream number.",
40818
- "",
40819
- "How to use NTRP (after vitals) \u2014 ask in English, peek at the glossary without a key, teach your desktop AI an inbox once, then stay in diagnose \u2192 plan \u2192 review."
40834
+ "Read in order: Freshness (is the number true?) \u2192 Flow + Drop (stuck / handoff) \u2192 Signal + Thread (busywork / thin deals).",
40835
+ "Freshness, Flow, and Drop feel familiar. Signal:Noise and Thread Depth are NTRP names.",
40836
+ "Then ask: what should I do next?"
40820
40837
  ];
40821
40838
  TOUR_CLOSE_LINES = [
40822
40839
  "A good first loop: ask something you actually care about \u2192 confirm the scope \u2192 load data (demo is fine) \u2192 let the formulas run. Then poke around:",
@@ -43059,6 +43076,7 @@ var init_prompt_parts = __esm({
43059
43076
  init_profile();
43060
43077
  init_store();
43061
43078
  init_gtm_counsel();
43079
+ init_metric_definitions();
43062
43080
  init_playbook();
43063
43081
  init_play_outcomes();
43064
43082
  init_registry2();
@@ -43095,16 +43113,7 @@ Restraint matters: NTRP is a stethoscope, not a surgeon. Observe, connect, and r
43095
43113
  - Observe, connect, recommend \u2014 never execute CRM changes, send email, or claim an action was taken unless a tool result in this conversation confirms it.
43096
43114
  - Weak or empty tool result: vary the arguments or approach once before concluding; if it's still empty, say what you'd need rather than filling the gap with plausible-sounding numbers.
43097
43115
  - Never fabricate CRM records, people, companies, or dollar amounts.`;
43098
- VITAL_SIGNS_BLOCK = `- freshness: Data recency. Low = stale contacts, zombie deals. Dollar value = pipeline at risk from stale accounts.
43099
- Expert read: cut by owner and by stage first \u2014 freshness reds concentrate on people or process, rarely evenly. In a long-cycle enterprise motion 30 quiet days can be normal cadence; in a velocity motion it's a dead deal. A sudden cliff usually means a broken integration or a departed rep, not gradual decay. False positive to check: bulk-imported records nobody has touched yet.
43100
- - flow_rate: Deal velocity. Low = stuck pipeline, slow progression. Dollar value = amount stuck in pipeline.
43101
- Expert read: cut by stage-age, not just deal-age \u2014 find the stage where deals go to die (usually one). Compare stuck-deal age to this company's own median cycle, not a generic norm. Stuck + past-due close dates together signal happy-ears forecasting, a credibility problem before it's a revenue problem.
43102
- - drop_rate: Handoff retention. Low = leads vanishing between marketing and sales. Dollar value = estimated lost revenue at handoff.
43103
- Expert read: this is almost always a systems failure \u2014 routing rules, unassigned territories, dead rep queues, or a sync gap between marketing and CRM \u2014 not lazy reps. First cut by lead source; the leak usually concentrates in one or two sources. The cheapest pipeline this business can buy is the leads it already paid for.
43104
- - signal_to_noise: Activity efficiency. Low = effort aimed at dead ends. Dollar value = cost of misdirected effort.
43105
- Expert read: cut by rep and by account status \u2014 noise usually means reps fishing in the pond they can see (dead accounts they know) because targeting and account lists are stale. Persistent noise is a coverage-model problem, not a coaching problem. Check whether activity is logged against closed or unlinked records \u2014 often a hygiene artifact.
43106
- - thread_depth: Deal resilience. Low = single-threaded deals, fragile pipeline. Dollar value = amount in single-threaded deals.
43107
- Expert read: weight by deal size \u2014 one single-threaded mega-deal outweighs ten small ones. Single-threading late in the cycle is far more dangerous than early. In enterprise motions, thread depth is a leading indicator of slipped quarters: champions change jobs, and there's no second door in.`;
43116
+ VITAL_SIGNS_BLOCK = buildVitalSignsPromptBlock();
43108
43117
  PLAYBOOK_BLOCK = `- "Multi-Thread Your Deals" (id: multi-thread-deals) \u2014 when thread_depth is low
43109
43118
  - "Clean Dead Pipeline" (id: clean-dead-pipeline) \u2014 when freshness is low
43110
43119
  - "Fix the Handoff Gap" (id: fix-handoff-gap) \u2014 when drop_rate is high and the source\u2192owner path is unknown
@@ -45759,12 +45768,89 @@ var init_health_chat = __esm({
45759
45768
  }
45760
45769
  });
45761
45770
 
45771
+ // src/conversation/next-move-chat.ts
45772
+ var next_move_chat_exports = {};
45773
+ __export(next_move_chat_exports, {
45774
+ NEXT_MOVE_EMPTY_LINE: () => NEXT_MOVE_EMPTY_LINE,
45775
+ everydayPlayReason: () => everydayPlayReason,
45776
+ isNextMoveChatPhase: () => isNextMoveChatPhase,
45777
+ isNextMoveIntent: () => isNextMoveIntent,
45778
+ resolveNextMove: () => resolveNextMove,
45779
+ tryNextMoveChat: () => tryNextMoveChat
45780
+ });
45781
+ import chalk95 from "chalk";
45782
+ function isNextMoveIntent(line) {
45783
+ const text = line.trim();
45784
+ if (!text) return false;
45785
+ if (/^(\/strategy|strategy)\b/i.test(text)) return false;
45786
+ return NEXT_MOVE_INTENT_RE.test(text);
45787
+ }
45788
+ function isNextMoveChatPhase(ctx) {
45789
+ const phase = resolveConversationPhase(ctx);
45790
+ return phase === "explore" || phase === "orient" && isAnalysisReady(ctx);
45791
+ }
45792
+ function everydayPlayReason(why) {
45793
+ const plain = why.replace(/\s+/g, " ").trim();
45794
+ if (!plain) return "";
45795
+ const match = plain.match(/^(.+?[.!?])(\s|$)/);
45796
+ const sentence = (match ? match[1] : plain).trim();
45797
+ return sentence.endsWith(".") || sentence.endsWith("!") || sentence.endsWith("?") ? sentence : `${sentence}.`;
45798
+ }
45799
+ function resolveNextMove(ctx) {
45800
+ const aggregate = ctx.snapshot.computeResult?.aggregate;
45801
+ if (!aggregate?.gating_vital_sign) return null;
45802
+ const gating = aggregate.gating_vital_sign;
45803
+ const play = getPlaysForVitalSign(gating)[0];
45804
+ if (!play) return null;
45805
+ const reason = everydayPlayReason(play.why);
45806
+ if (!reason) return null;
45807
+ return {
45808
+ playId: play.id,
45809
+ playName: play.name,
45810
+ reason,
45811
+ gatingVital: VITAL_SIGN_LABELS[gating] ?? gating
45812
+ };
45813
+ }
45814
+ function tryNextMoveChat(ctx, line) {
45815
+ if (!isNextMoveIntent(line)) return false;
45816
+ if (!isNextMoveChatPhase(ctx)) return false;
45817
+ const move = resolveNextMove(ctx);
45818
+ console.log();
45819
+ if (!move) {
45820
+ console.log(" " + NEXT_MOVE_EMPTY_LINE);
45821
+ console.log();
45822
+ recordMessage(ctx, "user", line);
45823
+ recordMessage(ctx, "agent", NEXT_MOVE_EMPTY_LINE);
45824
+ saveSessionState(ctx);
45825
+ return true;
45826
+ }
45827
+ console.log(" " + chalk95.bold(move.playName));
45828
+ console.log(" " + move.reason);
45829
+ console.log();
45830
+ recordMessage(ctx, "user", line);
45831
+ recordMessage(ctx, "agent", `${move.playName} \u2014 ${move.reason}`);
45832
+ saveSessionState(ctx);
45833
+ return true;
45834
+ }
45835
+ var NEXT_MOVE_EMPTY_LINE, NEXT_MOVE_INTENT_RE;
45836
+ var init_next_move_chat = __esm({
45837
+ "src/conversation/next-move-chat.ts"() {
45838
+ "use strict";
45839
+ init_context2();
45840
+ init_playbook();
45841
+ init_formatters();
45842
+ init_phase();
45843
+ NEXT_MOVE_EMPTY_LINE = "Nothing clear to recommend yet. Ask how healthy the pipeline looks.";
45844
+ NEXT_MOVE_INTENT_RE = /\b((what\s+should\s+i\s+do\s+next)|((what'?s|whats|what\s+is)\s+(the\s+)?next\s+move)|((what'?s|whats|what\s+is)\s+my\s+next\s+move))\b/i;
45845
+ }
45846
+ });
45847
+
45762
45848
  // src/conversation/router.ts
45763
45849
  var router_exports = {};
45764
45850
  __export(router_exports, {
45765
45851
  conversationRouter: () => conversationRouter
45766
45852
  });
45767
- import chalk95 from "chalk";
45853
+ import chalk96 from "chalk";
45768
45854
  function popModalState(ctx) {
45769
45855
  const popped = [];
45770
45856
  if (ctx.strategistState) {
@@ -45797,7 +45883,7 @@ function handleBackNavigation(ctx, line) {
45797
45883
  }
45798
45884
  if (phase === "scope") {
45799
45885
  console.log();
45800
- console.log(" " + chalk95.dim("What should we focus on instead?"));
45886
+ console.log(" " + chalk96.dim("What should we focus on instead?"));
45801
45887
  ctx.scope = void 0;
45802
45888
  clearPendingAsk(ctx);
45803
45889
  saveSessionState(ctx);
@@ -45817,7 +45903,7 @@ function handleBackNavigation(ctx, line) {
45817
45903
  printScopeProposal(ctx);
45818
45904
  if (hadData || hadAnalysis) {
45819
45905
  console.log(
45820
- " " + chalk95.dim(
45906
+ " " + chalk96.dim(
45821
45907
  "Focus gate rewound \u2014 loaded data and any analysis stay. `b` does not unload demo data or undo compute."
45822
45908
  )
45823
45909
  );
@@ -45833,7 +45919,7 @@ function handleBackNavigation(ctx, line) {
45833
45919
  recordMessage(ctx, "user", line);
45834
45920
  recordMessage(ctx, "agent", "Strategy objective adjust (back)");
45835
45921
  console.log();
45836
- console.log(" " + chalk95.dim("What is the objective? State a finish line."));
45922
+ console.log(" " + chalk96.dim("What is the objective? State a finish line."));
45837
45923
  console.log();
45838
45924
  return { handled: true, summary: "Awaiting objective" };
45839
45925
  }
@@ -45845,7 +45931,7 @@ function handleBackNavigation(ctx, line) {
45845
45931
  const backTo = formatPhaseLabel(resolveConversationPhase(ctx));
45846
45932
  console.log();
45847
45933
  console.log(
45848
- " " + chalk95.dim(`Back \u2014 dropped ${popped.join(" and ")}. At `) + chalk95.cyan(backTo) + chalk95.dim(".")
45934
+ " " + chalk96.dim(`Back \u2014 dropped ${popped.join(" and ")}. At `) + chalk96.cyan(backTo) + chalk96.dim(".")
45849
45935
  );
45850
45936
  console.log();
45851
45937
  return { handled: true, summary: "Back" };
@@ -45859,7 +45945,7 @@ function handleBackNavigation(ctx, line) {
45859
45945
  const backTo = formatPhaseLabel(resolveConversationPhase(ctx));
45860
45946
  console.log();
45861
45947
  console.log(
45862
- " " + chalk95.dim(`Back \u2014 dropped ${popped.join(" and ")}. At `) + chalk95.cyan(backTo) + chalk95.dim(".")
45948
+ " " + chalk96.dim(`Back \u2014 dropped ${popped.join(" and ")}. At `) + chalk96.cyan(backTo) + chalk96.dim(".")
45863
45949
  );
45864
45950
  console.log();
45865
45951
  return { handled: true, summary: "Back" };
@@ -45903,7 +45989,7 @@ async function conversationRouter(input, ctx) {
45903
45989
  if (!ok) {
45904
45990
  console.log();
45905
45991
  console.log(
45906
- " " + chalk95.dim("Staying on this session. Type ") + chalk95.cyan("/home") + chalk95.dim(" for the dashboard.")
45992
+ " " + chalk96.dim("Staying on this session. Type ") + chalk96.cyan("/home") + chalk96.dim(" for the dashboard.")
45907
45993
  );
45908
45994
  console.log();
45909
45995
  return { handled: true };
@@ -45918,7 +46004,7 @@ async function conversationRouter(input, ctx) {
45918
46004
  }
45919
46005
  console.log();
45920
46006
  console.log(
45921
- " " + chalk95.dim("Start a fresh analysis with ") + chalk95.cyan("/new") + chalk95.dim(" \u2014 or ") + chalk95.cyan("/home") + chalk95.dim(" for the dashboard.")
46007
+ " " + chalk96.dim("Start a fresh analysis with ") + chalk96.cyan("/new") + chalk96.dim(" \u2014 or ") + chalk96.cyan("/home") + chalk96.dim(" for the dashboard.")
45922
46008
  );
45923
46009
  console.log();
45924
46010
  return { handled: true };
@@ -45932,7 +46018,7 @@ async function conversationRouter(input, ctx) {
45932
46018
  const backTo = formatPhaseLabel(resolveConversationPhase(ctx));
45933
46019
  console.log();
45934
46020
  console.log(
45935
- " " + chalk95.dim(`Cancelled \u2014 dropped ${popped.join(" and ")}. Back to `) + chalk95.cyan(backTo) + chalk95.dim(".")
46021
+ " " + chalk96.dim(`Cancelled \u2014 dropped ${popped.join(" and ")}. Back to `) + chalk96.cyan(backTo) + chalk96.dim(".")
45936
46022
  );
45937
46023
  console.log();
45938
46024
  return { handled: true, summary: "Cancelled" };
@@ -45982,6 +46068,12 @@ async function conversationRouter(input, ctx) {
45982
46068
  return { handled: true, summary: "Pipeline health" };
45983
46069
  }
45984
46070
  }
46071
+ if (phase === "explore" || phase === "orient" && isAnalysisReady(ctx)) {
46072
+ const { tryNextMoveChat: tryNextMoveChat2 } = await Promise.resolve().then(() => (init_next_move_chat(), next_move_chat_exports));
46073
+ if (tryNextMoveChat2(ctx, line)) {
46074
+ return { handled: true, summary: "Next move" };
46075
+ }
46076
+ }
45985
46077
  if (phase === "think") {
45986
46078
  const summary = await handleThinkFlow(line, ctx) ?? void 0;
45987
46079
  return { handled: true, summary };
@@ -46020,7 +46112,7 @@ async function conversationRouter(input, ctx) {
46020
46112
  }
46021
46113
  if (phase === "compute") {
46022
46114
  console.log();
46023
- console.log(" " + chalk95.dim("Analysis running \u2014 wait for it to finish before typing another question."));
46115
+ console.log(" " + chalk96.dim("Analysis running \u2014 wait for it to finish before typing another question."));
46024
46116
  console.log();
46025
46117
  return { handled: true };
46026
46118
  }
@@ -46076,7 +46168,7 @@ __export(dispatch_exports, {
46076
46168
  dispatch: () => dispatch,
46077
46169
  replayPendingBlockedLine: () => replayPendingBlockedLine
46078
46170
  });
46079
- import chalk96 from "chalk";
46171
+ import chalk97 from "chalk";
46080
46172
  function printLicenseRequired(command) {
46081
46173
  printLicenseBlocked(command);
46082
46174
  }
@@ -46094,7 +46186,7 @@ async function replayPendingBlockedLine(ctx) {
46094
46186
  if (!hasValidLicense()) return false;
46095
46187
  ctx.pendingBlockedLine = void 0;
46096
46188
  console.log();
46097
- console.log(" " + chalk96.dim("Picking up where you left off\u2026"));
46189
+ console.log(" " + chalk97.dim("Picking up where you left off\u2026"));
46098
46190
  console.log();
46099
46191
  await dispatch(line, ctx);
46100
46192
  return true;
@@ -46164,7 +46256,7 @@ async function dispatch(input, ctx) {
46164
46256
  if (tokens.length === 1) {
46165
46257
  if (/^\d$/.test(first)) {
46166
46258
  console.log(
46167
- " " + chalk96.dim("Looks like a menu pick \u2014 run ") + paint("accent", "/new") + chalk96.dim(" to start (pick Demo, then choose your analysis type).")
46259
+ " " + chalk97.dim("Looks like a menu pick \u2014 run ") + paint("accent", "/new") + chalk97.dim(" to start (pick Demo, then choose your analysis type).")
46168
46260
  );
46169
46261
  return { kind: "handled" };
46170
46262
  }
@@ -46187,19 +46279,19 @@ async function dispatch(input, ctx) {
46187
46279
  return { kind: "handled", summary };
46188
46280
  }
46189
46281
  console.log(
46190
- " " + chalk96.dim("Not in Q&A yet. Confirm the scope, load data, and run analysis first. Type ") + paint("accent", "/home") + chalk96.dim(" for status.")
46282
+ " " + chalk97.dim("Not in Q&A yet. Confirm the scope, load data, and run analysis first. Type ") + paint("accent", "/home") + chalk97.dim(" for status.")
46191
46283
  );
46192
46284
  return { kind: "handled" };
46193
46285
  }
46194
46286
  console.log(
46195
- " " + chalk96.dim("Natural-language questions run inside ntrp. Start with ") + paint("accent", "ntrp") + chalk96.dim(" and type a question after analysis.")
46287
+ " " + chalk97.dim("Natural-language questions run inside ntrp. Start with ") + paint("accent", "ntrp") + chalk97.dim(" and type a question after analysis.")
46196
46288
  );
46197
46289
  return { kind: "handled" };
46198
46290
  }
46199
46291
  async function runSlashCommand(name, args, ctx) {
46200
46292
  const handler54 = await resolveHandler(name);
46201
46293
  if (!handler54) {
46202
- console.error(chalk96.red(` Unknown command: /${name}`));
46294
+ console.error(chalk97.red(` Unknown command: /${name}`));
46203
46295
  return void 0;
46204
46296
  }
46205
46297
  const result = await handler54(args, ctx);
@@ -46236,7 +46328,7 @@ var init_inline_suggestion = __esm({
46236
46328
  });
46237
46329
 
46238
46330
  // src/conversation/loop-guard.ts
46239
- import chalk97 from "chalk";
46331
+ import chalk98 from "chalk";
46240
46332
  function createLoopGuardState() {
46241
46333
  return { phase: null, stuckTurns: 0 };
46242
46334
  }
@@ -46268,10 +46360,10 @@ function printLoopEscalation(phase) {
46268
46360
  if (!guide) return;
46269
46361
  console.log();
46270
46362
  console.log(
46271
- " " + chalk97.yellow("We seem to be going in circles \u2014 you're in ") + paint("accent", guide.mode) + chalk97.yellow(" mode.")
46363
+ " " + chalk98.yellow("We seem to be going in circles \u2014 you're in ") + paint("accent", guide.mode) + chalk98.yellow(" mode.")
46272
46364
  );
46273
- console.log(" " + chalk97.dim("Right now I can only accept: ") + guide.accepts);
46274
- console.log(" " + chalk97.dim("To leave: ") + guide.leave);
46365
+ console.log(" " + chalk98.dim("Right now I can only accept: ") + guide.accepts);
46366
+ console.log(" " + chalk98.dim("To leave: ") + guide.leave);
46275
46367
  console.log();
46276
46368
  }
46277
46369
  var LOOP_GUARD_THRESHOLD, MODAL_PHASES, PHASE_GUIDES;
@@ -46315,7 +46407,7 @@ __export(welcome_exports, {
46315
46407
  resolveWelcomeNextAction: () => resolveWelcomeNextAction,
46316
46408
  staleProcessHomeNotice: () => staleProcessHomeNotice
46317
46409
  });
46318
- import chalk98 from "chalk";
46410
+ import chalk99 from "chalk";
46319
46411
  function formatHomeEntityCounts(counts) {
46320
46412
  const parts = [];
46321
46413
  const people = counts.people ?? 0;
@@ -46329,11 +46421,11 @@ function formatHomeEntityCounts(counts) {
46329
46421
  return parts.join(" \xB7 ");
46330
46422
  }
46331
46423
  function formatEmptyDataHomeHint(savedSessionCount, opts = {}) {
46332
- const onboard = opts.includeOnboard === true ? chalk98.dim(", or ") + paint("accent", "/onboard") + chalk98.dim(" to calibrate") : "";
46424
+ const onboard = opts.includeOnboard === true ? chalk99.dim(", or ") + paint("accent", "/onboard") + chalk99.dim(" to calibrate") : "";
46333
46425
  if (savedSessionCount > 0) {
46334
- return chalk98.dim("Drop a CSV or type ") + paint("accent", "use demo data") + chalk98.dim(" to load a sample") + onboard + chalk98.dim(". Type ") + paint("accent", "/session") + chalk98.dim(" to open a saved session");
46426
+ return chalk99.dim("Drop a CSV or type ") + paint("accent", "use demo data") + chalk99.dim(" to load a sample") + onboard + chalk99.dim(". Type ") + paint("accent", "/session") + chalk99.dim(" to open a saved session");
46335
46427
  }
46336
- return chalk98.dim("Drop a CSV or type ") + paint("accent", "use demo data") + chalk98.dim(" to load a sample pipeline") + onboard;
46428
+ return chalk99.dim("Drop a CSV or type ") + paint("accent", "use demo data") + chalk99.dim(" to load a sample pipeline") + onboard;
46337
46429
  }
46338
46430
  function staleProcessHomeNotice() {
46339
46431
  const running = getInstalledVersion();
@@ -46375,19 +46467,19 @@ function sessionSummaryText(s) {
46375
46467
  summary: s.summary,
46376
46468
  dataset: s.dataset
46377
46469
  });
46378
- return summary === NO_SUMMARY ? chalk98.dim(summary) : summary;
46470
+ return summary === NO_SUMMARY ? chalk99.dim(summary) : summary;
46379
46471
  }
46380
46472
  function formatLastSessionLine(s, colW, ctx, opts) {
46381
46473
  const phase = sessionPhaseLabel(s, ctx);
46382
- const current = opts?.markCurrent && s.id === ctx?.sessionId ? chalk98.dim(" \xB7 current") : "";
46383
- const meta = `${formatSessionId(s.id, s.name)} ${chalk98.dim("\xB7")} ${chalk98.dim(lensBadgeLabel(s.analysis))} ${chalk98.dim("\xB7")} ${paint("accent", phase)} ${chalk98.dim("\xB7")} ${sessionSummaryText(s)}${current}`;
46474
+ const current = opts?.markCurrent && s.id === ctx?.sessionId ? chalk99.dim(" \xB7 current") : "";
46475
+ const meta = `${formatSessionId(s.id, s.name)} ${chalk99.dim("\xB7")} ${chalk99.dim(lensBadgeLabel(s.analysis))} ${chalk99.dim("\xB7")} ${paint("accent", phase)} ${chalk99.dim("\xB7")} ${sessionSummaryText(s)}${current}`;
46384
46476
  return truncateVisible(` ${meta}`, colW);
46385
46477
  }
46386
46478
  function formatActiveSessionLine(s, colW, ctx, opts) {
46387
46479
  const indent = " ";
46388
46480
  const idPart = formatSessionId(s.id, s.name);
46389
- const status = chalk98.dim(` \xB7 ${sessionStatusSuffix(s)}`);
46390
- const current = opts?.markCurrent && s.id === ctx?.sessionId ? chalk98.dim(" \xB7 current") : "";
46481
+ const status = chalk99.dim(` \xB7 ${sessionStatusSuffix(s)}`);
46482
+ const current = opts?.markCurrent && s.id === ctx?.sessionId ? chalk99.dim(" \xB7 current") : "";
46391
46483
  const suffix = `${status}${current}`;
46392
46484
  const summaryBudget = Math.max(8, colW - visibleWidth(indent) - visibleWidth(idPart) - visibleWidth(suffix) - 2);
46393
46485
  const summaryPart = truncateVisible(sessionSummaryText(s), summaryBudget);
@@ -46428,13 +46520,13 @@ function buildSystemLines(colW, statusRows, recent) {
46428
46520
  lines.push(sectionHeading("System"));
46429
46521
  const labelW = Math.max(...statusRows.map((r) => r.label.length), "last used".length);
46430
46522
  for (const item of statusRows) {
46431
- const label = chalk98.dim(padRight(item.label, labelW));
46523
+ const label = chalk99.dim(padRight(item.label, labelW));
46432
46524
  const state2 = padRight(item.state, 10);
46433
46525
  const detailW = Math.max(1, colW - labelW - 13);
46434
- lines.push(`${label} ${state2} ${chalk98.dim(truncateVisible(item.detail, detailW))}`);
46526
+ lines.push(`${label} ${state2} ${chalk99.dim(truncateVisible(item.detail, detailW))}`);
46435
46527
  }
46436
46528
  if (recent) {
46437
- lines.push(`${chalk98.dim(padRight("last used", labelW))} ${chalk98.dim(recent)}`);
46529
+ lines.push(`${chalk99.dim(padRight("last used", labelW))} ${chalk99.dim(recent)}`);
46438
46530
  }
46439
46531
  return lines;
46440
46532
  }
@@ -46442,10 +46534,10 @@ function buildLastSessionLines(colW, ctx, lastSession, nextAction, emptyDataHint
46442
46534
  const lines = [""];
46443
46535
  lines.push(sectionHeading("Last Session"));
46444
46536
  if (!lastSession) {
46445
- lines.push(` ${chalk98.dim("(none)")}`);
46537
+ lines.push(` ${chalk99.dim("(none)")}`);
46446
46538
  lines.push(
46447
46539
  truncateVisible(
46448
- ` ${nextAction.command ? actionHint(nextAction.label, nextAction.command, nextAction.detail) : `${chalk98.dim(nextAction.label)} ${chalk98.dim(nextAction.detail)}`}`,
46540
+ ` ${nextAction.command ? actionHint(nextAction.label, nextAction.command, nextAction.detail) : `${chalk99.dim(nextAction.label)} ${chalk99.dim(nextAction.detail)}`}`,
46449
46541
  colW
46450
46542
  )
46451
46543
  );
@@ -46459,7 +46551,7 @@ function buildLastSessionLines(colW, ctx, lastSession, nextAction, emptyDataHint
46459
46551
  if (!isCurrent) {
46460
46552
  lines.push(
46461
46553
  truncateVisible(
46462
- ` ${chalk98.dim("Resume:")} ${paint("accent", `/session ${lastSession.id.slice(-4)}`)}`,
46554
+ ` ${chalk99.dim("Resume:")} ${paint("accent", `/session ${lastSession.id.slice(-4)}`)}`,
46463
46555
  colW
46464
46556
  )
46465
46557
  );
@@ -46468,7 +46560,7 @@ function buildLastSessionLines(colW, ctx, lastSession, nextAction, emptyDataHint
46468
46560
  truncateVisible(` ${actionHint(nextAction.label, nextAction.command, nextAction.detail)}`, colW)
46469
46561
  );
46470
46562
  } else {
46471
- lines.push(truncateVisible(` ${chalk98.dim(nextAction.label)} ${chalk98.dim(nextAction.detail)}`, colW));
46563
+ lines.push(truncateVisible(` ${chalk99.dim(nextAction.label)} ${chalk99.dim(nextAction.detail)}`, colW));
46472
46564
  }
46473
46565
  if (isCurrent && emptyDataHint) {
46474
46566
  lines.push(truncateVisible(` ${emptyDataHint}`, colW));
@@ -46479,14 +46571,14 @@ function buildActiveSessionsLines(colW, ctx, activeSessions) {
46479
46571
  const lines = [""];
46480
46572
  lines.push(sectionHeading("Active Sessions"));
46481
46573
  if (activeSessions.length === 0) {
46482
- lines.push(` ${chalk98.dim("(none in progress)")}`);
46574
+ lines.push(` ${chalk99.dim("(none in progress)")}`);
46483
46575
  return lines;
46484
46576
  }
46485
46577
  for (const s of activeSessions.slice(0, 5)) {
46486
46578
  lines.push(formatActiveSessionLine(s, colW, ctx, { markCurrent: true }));
46487
46579
  }
46488
46580
  if (activeSessions.length > 5) {
46489
- lines.push(` ${chalk98.dim(`+${activeSessions.length - 5} more \xB7 `)}${paint("accent", "/session")}`);
46581
+ lines.push(` ${chalk99.dim(`+${activeSessions.length - 5} more \xB7 `)}${paint("accent", "/session")}`);
46490
46582
  }
46491
46583
  return lines;
46492
46584
  }
@@ -46574,7 +46666,7 @@ async function printWelcome(ctx, version) {
46574
46666
  const gap = Math.max(0, innerW - versionTag.length);
46575
46667
  const gapL = Math.floor(gap / 2);
46576
46668
  push(
46577
- border(`\u256D${"\u2500".repeat(gapL)}`) + chalk98.dim(versionTag) + border(`${"\u2500".repeat(gap - gapL)}\u256E`)
46669
+ border(`\u256D${"\u2500".repeat(gapL)}`) + chalk99.dim(versionTag) + border(`${"\u2500".repeat(gap - gapL)}\u256E`)
46578
46670
  );
46579
46671
  if (useWideLayout) {
46580
46672
  const leftLines = systemLines;
@@ -46601,7 +46693,7 @@ async function printWelcome(ctx, version) {
46601
46693
  push(border(`\u2570${"\u2500".repeat(innerW)}\u256F`));
46602
46694
  push(
46603
46695
  truncateVisible(
46604
- license.valid ? ` ${paint("accent", "/help")}${chalk98.dim(" commands \xB7 ")}${paint("accent", "/tour")}${chalk98.dim(" tour \xB7 ")}${paint("accent", "/progress")}${chalk98.dim(" hours \xB7 ")}${paint("accent", "/session")}${chalk98.dim(" resume")}` : ` ${paint("accent", "/help")}${chalk98.dim(" commands \xB7 ")}${paint("accent", "/activate")}${chalk98.dim(" paste a key \xB7 ")}${paint("accent", "/checkout")}${chalk98.dim(" signup \xB7 ")}${paint("accent", "/progress")}${chalk98.dim(" hours")}`,
46696
+ license.valid ? ` ${paint("accent", "/help")}${chalk99.dim(" commands \xB7 ")}${paint("accent", "/tour")}${chalk99.dim(" tour \xB7 ")}${paint("accent", "/progress")}${chalk99.dim(" hours \xB7 ")}${paint("accent", "/session")}${chalk99.dim(" resume")}` : ` ${paint("accent", "/help")}${chalk99.dim(" commands \xB7 ")}${paint("accent", "/activate")}${chalk99.dim(" paste a key \xB7 ")}${paint("accent", "/checkout")}${chalk99.dim(" signup \xB7 ")}${paint("accent", "/progress")}${chalk99.dim(" hours")}`,
46605
46697
  cardW
46606
46698
  )
46607
46699
  );
@@ -46612,7 +46704,7 @@ async function printWelcome(ctx, version) {
46612
46704
  if (strategyNudge) {
46613
46705
  push(
46614
46706
  truncateVisible(
46615
- ` ${paint("warning", "\u2691")} ${chalk98.dim(strategyNudge.text)} ${chalk98.dim("\xB7")} ${paint("accent", strategyNudge.command)}`,
46707
+ ` ${paint("warning", "\u2691")} ${chalk99.dim(strategyNudge.text)} ${chalk99.dim("\xB7")} ${paint("accent", strategyNudge.command)}`,
46616
46708
  cardW
46617
46709
  )
46618
46710
  );
@@ -46620,7 +46712,7 @@ async function printWelcome(ctx, version) {
46620
46712
  const tip = deepdiveNudge.tip ?? deepdiveNudge.command;
46621
46713
  push(
46622
46714
  truncateVisible(
46623
- tip ? ` ${paint("warning", "\u2691")} ${chalk98.dim(deepdiveNudge.text)} ${chalk98.dim("\xB7")} ${chalk98.dim(tip)}` : ` ${paint("warning", "\u2691")} ${chalk98.dim(deepdiveNudge.text)}`,
46715
+ tip ? ` ${paint("warning", "\u2691")} ${chalk99.dim(deepdiveNudge.text)} ${chalk99.dim("\xB7")} ${chalk99.dim(tip)}` : ` ${paint("warning", "\u2691")} ${chalk99.dim(deepdiveNudge.text)}`,
46624
46716
  cardW
46625
46717
  )
46626
46718
  );
@@ -46628,7 +46720,7 @@ async function printWelcome(ctx, version) {
46628
46720
  } else if (voiceNudge) {
46629
46721
  push(
46630
46722
  truncateVisible(
46631
- ` ${paint("warning", "\u2691")} ${chalk98.dim(voiceNudge.text)} ${chalk98.dim("\xB7")} ${paint("accent", voiceNudge.command)}`,
46723
+ ` ${paint("warning", "\u2691")} ${chalk99.dim(voiceNudge.text)} ${chalk99.dim("\xB7")} ${paint("accent", voiceNudge.command)}`,
46632
46724
  cardW
46633
46725
  )
46634
46726
  );
@@ -46816,7 +46908,7 @@ __export(repl_exports, {
46816
46908
  });
46817
46909
  import { createInterface as createInterface2 } from "readline/promises";
46818
46910
  import { clearLine as clearLine2, cursorTo as cursorTo2 } from "readline";
46819
- import chalk99 from "chalk";
46911
+ import chalk100 from "chalk";
46820
46912
  import { join as join42 } from "path";
46821
46913
  function buildPrompt(ctx) {
46822
46914
  return buildConversationPrompt(ctx);
@@ -46908,12 +47000,12 @@ function renderInlineSuggestion(rl, prompt, ctx) {
46908
47000
  suggestionPainted = suffix !== null;
46909
47001
  clearLine2(process.stdout, 0);
46910
47002
  cursorTo2(process.stdout, 0);
46911
- process.stdout.write(prompt + line + (suffix ? chalk99.dim(suffix) : ""));
47003
+ process.stdout.write(prompt + line + (suffix ? chalk100.dim(suffix) : ""));
46912
47004
  cursorTo2(process.stdout, promptWidth + cursor);
46913
47005
  }
46914
47006
  function appendTurnLine(current, promptLabel, currentSummary) {
46915
- const currentLine = currentSummary ? `${promptLabel} ${current} ${chalk99.white("\u2192")} ${currentSummary}` : `${promptLabel} ${current}`;
46916
- console.log(" " + chalk99.dim(currentLine));
47007
+ const currentLine = currentSummary ? `${promptLabel} ${current} ${chalk100.white("\u2192")} ${currentSummary}` : `${promptLabel} ${current}`;
47008
+ console.log(" " + chalk100.dim(currentLine));
46917
47009
  console.log();
46918
47010
  }
46919
47011
  async function goHome(ctx, version, history, opts) {
@@ -46923,7 +47015,7 @@ async function goHome(ctx, version, history, opts) {
46923
47015
  clearTerminalHome();
46924
47016
  if (opts?.banner) {
46925
47017
  console.log();
46926
- console.log(" " + paint("accent", "\u2713") + " " + chalk99.dim(opts.banner));
47018
+ console.log(" " + paint("accent", "\u2713") + " " + chalk100.dim(opts.banner));
46927
47019
  }
46928
47020
  await printWelcome(ctx, version);
46929
47021
  }
@@ -46946,11 +47038,11 @@ async function handleDispatchResult(result, ctx, version, history) {
46946
47038
  case "unknown":
46947
47039
  if (result.suggestion) {
46948
47040
  console.log(
46949
- " " + chalk99.red(`Unknown command: ${result.token}.`) + chalk99.dim(" Did you mean ") + paint("accent", result.suggestion) + chalk99.dim("?")
47041
+ " " + chalk100.red(`Unknown command: ${result.token}.`) + chalk100.dim(" Did you mean ") + paint("accent", result.suggestion) + chalk100.dim("?")
46950
47042
  );
46951
47043
  } else {
46952
47044
  console.log(
46953
- " " + chalk99.red(`Unknown command: ${result.token}`) + chalk99.dim(" Type ") + paint("accent", "/help") + chalk99.dim(" to see available commands.")
47045
+ " " + chalk100.red(`Unknown command: ${result.token}`) + chalk100.dim(" Type ") + paint("accent", "/help") + chalk100.dim(" to see available commands.")
46954
47046
  );
46955
47047
  }
46956
47048
  break;
@@ -46974,7 +47066,7 @@ async function runRepl(ctx, version) {
46974
47066
  });
46975
47067
  ctx.rl = rl;
46976
47068
  console.log();
46977
- console.log(" " + chalk99.dim("What do you want to look at?"));
47069
+ console.log(" " + chalk100.dim("What do you want to look at?"));
46978
47070
  console.log();
46979
47071
  if (ctx.pendingUpdateCheck) {
46980
47072
  void ctx.pendingUpdateCheck.then((result) => {
@@ -47016,7 +47108,7 @@ async function runRepl(ctx, version) {
47016
47108
  return;
47017
47109
  }
47018
47110
  sigintPrimed = true;
47019
- console.log("\n " + chalk99.dim("Type /exit to quit, or press Ctrl+C again."));
47111
+ console.log("\n " + chalk100.dim("Type /exit to quit, or press Ctrl+C again."));
47020
47112
  };
47021
47113
  rl.on("SIGINT", sigintHandler);
47022
47114
  function shutdownRepl() {
@@ -47053,7 +47145,7 @@ async function runRepl(ctx, version) {
47053
47145
  if (!typed && !enterAction) {
47054
47146
  clearGhostRowAfterSubmit();
47055
47147
  const coach = consumeOrientEmptyEnterCoach(ctx);
47056
- if (coach) console.log(" " + chalk99.dim(coach));
47148
+ if (coach) console.log(" " + chalk100.dim(coach));
47057
47149
  continue;
47058
47150
  }
47059
47151
  const line = typed || enterAction.submit;
@@ -47104,11 +47196,11 @@ async function runRepl(ctx, version) {
47104
47196
  ctx.wizardDepth = 0;
47105
47197
  ctx.secretInputActive = false;
47106
47198
  if (err instanceof Error && err.message === "Cancelled") {
47107
- console.log(" " + chalk99.dim("Cancelled."));
47199
+ console.log(" " + chalk100.dim("Cancelled."));
47108
47200
  } else {
47109
47201
  const { tryRecoverLlmAuthFailure: tryRecoverLlmAuthFailure2 } = await Promise.resolve().then(() => (init_auth_recovery(), auth_recovery_exports));
47110
47202
  if (!await tryRecoverLlmAuthFailure2(ctx, err)) {
47111
- console.error(" " + chalk99.red("Error: " + String(err.message ?? err)));
47203
+ console.error(" " + chalk100.red("Error: " + String(err.message ?? err)));
47112
47204
  }
47113
47205
  }
47114
47206
  }
@@ -47135,10 +47227,10 @@ async function runRepl(ctx, version) {
47135
47227
  await closeSession(ctx);
47136
47228
  }
47137
47229
  if (isTranscriptActive(ctx.sessionId)) {
47138
- console.log(" " + chalk99.dim("Transcript: ") + chalk99.dim(transcriptPathForSession(ctx.sessionId)));
47139
- console.log(" " + chalk99.dim("Context brief: ") + chalk99.dim(contextDocPathForSession(ctx.sessionId)));
47230
+ console.log(" " + chalk100.dim("Transcript: ") + chalk100.dim(transcriptPathForSession(ctx.sessionId)));
47231
+ console.log(" " + chalk100.dim("Context brief: ") + chalk100.dim(contextDocPathForSession(ctx.sessionId)));
47140
47232
  }
47141
- console.log(" " + chalk99.dim(randomGoodbye()));
47233
+ console.log(" " + chalk100.dim(randomGoodbye()));
47142
47234
  }
47143
47235
  function printHelpOneShot() {
47144
47236
  printHelp();
@@ -47146,43 +47238,43 @@ function printHelpOneShot() {
47146
47238
  function printHelp() {
47147
47239
  console.log();
47148
47240
  console.log(" " + sectionHeading("Conversation"));
47149
- console.log(" " + chalk99.dim("Type the question. You do not need a slash command."));
47150
- console.log(" " + chalk99.dim("Paste a CSV path or type ") + paint("accent", '"use demo data"') + chalk99.dim(" to load data."));
47151
- console.log(" " + chalk99.dim("After analysis, type questions in English."));
47152
- console.log(" " + chalk99.dim("Type ") + paint("accent", '"how should we fix this?"') + chalk99.dim(" to make a strategy. Type ") + paint("accent", "keep going") + chalk99.dim(" at confirm to keep working until the plan is ready."));
47153
- console.log(" " + chalk99.dim("Type ") + paint("accent", '"ship a board deck"') + chalk99.dim(" to write a handoff."));
47154
- console.log(" " + chalk99.dim("The ") + paint("accent", "\u203A") + chalk99.dim(" prompt shows brief or deep after analysis. Brief is the default."));
47241
+ console.log(" " + chalk100.dim("Type the question. You do not need a slash command."));
47242
+ console.log(" " + chalk100.dim("Paste a CSV path or type ") + paint("accent", '"use demo data"') + chalk100.dim(" to load data."));
47243
+ console.log(" " + chalk100.dim("After analysis, type questions in English."));
47244
+ console.log(" " + chalk100.dim("Type ") + paint("accent", '"how should we fix this?"') + chalk100.dim(" to make a strategy. Type ") + paint("accent", "keep going") + chalk100.dim(" at confirm to keep working until the plan is ready."));
47245
+ console.log(" " + chalk100.dim("Type ") + paint("accent", '"ship a board deck"') + chalk100.dim(" to write a handoff."));
47246
+ console.log(" " + chalk100.dim("The ") + paint("accent", "\u203A") + chalk100.dim(" prompt shows brief or deep after analysis. Brief is the default."));
47155
47247
  console.log();
47156
47248
  console.log(" " + sectionHeading("Keys"));
47157
47249
  console.log(
47158
- " " + paint("accent", "\u23CE") + chalk99.dim(
47250
+ " " + paint("accent", "\u23CE") + chalk100.dim(
47159
47251
  " Accepts the default. At the main prompt it runs the armed action (yes, use demo data, go ahead, /connect, /update, keep going)."
47160
47252
  )
47161
47253
  );
47162
47254
  console.log(
47163
- " " + chalk99.dim(
47255
+ " " + chalk100.dim(
47164
47256
  " On yes/no questions and menus it accepts yes (or the recommended option). Type something else to decline or pick another path."
47165
47257
  )
47166
47258
  );
47167
47259
  console.log(
47168
- " " + paint("accent", "b") + chalk99.dim(" / ") + paint("accent", "back") + chalk99.dim(" Steps back one confirm gate, or leaves a modal. Does not unload data or undo compute.")
47260
+ " " + paint("accent", "b") + chalk100.dim(" / ") + paint("accent", "back") + chalk100.dim(" Steps back one confirm gate, or leaves a modal. Does not unload data or undo compute.")
47169
47261
  );
47170
47262
  console.log(
47171
- " " + chalk99.dim("On ") + paint("accent", "/settings") + chalk99.dim(" menus, ") + paint("accent", "b") + chalk99.dim(" leaves the hub (same as Done).")
47263
+ " " + chalk100.dim("On ") + paint("accent", "/settings") + chalk100.dim(" menus, ") + paint("accent", "b") + chalk100.dim(" leaves the hub (same as Done).")
47172
47264
  );
47173
47265
  console.log(
47174
- " " + paint("accent", "more") + chalk99.dim(" Shows the full strategy brief after the short summary.")
47266
+ " " + paint("accent", "more") + chalk100.dim(" Shows the full strategy brief after the short summary.")
47175
47267
  );
47176
47268
  console.log(
47177
- " " + paint("accent", "expand") + chalk99.dim(
47269
+ " " + paint("accent", "expand") + chalk100.dim(
47178
47270
  " After a short Q&A answer, shows more reasoning for that same answer. With no last answer, expands the strategy brief when one is on screen."
47179
47271
  )
47180
47272
  );
47181
47273
  console.log(
47182
- " " + paint("accent", "cancel") + chalk99.dim(" Drops the current modal overlay (strategy, think, ship, unconfirmed scope).")
47274
+ " " + paint("accent", "cancel") + chalk100.dim(" Drops the current modal overlay (strategy, think, ship, unconfirmed scope).")
47183
47275
  );
47184
47276
  console.log(
47185
- " " + chalk99.dim("On ") + paint("accent", "/tour") + chalk99.dim(" slides, ") + paint("accent", "b") + chalk99.dim(" moves to the previous slide.")
47277
+ " " + chalk100.dim("On ") + paint("accent", "/tour") + chalk100.dim(" slides, ") + paint("accent", "b") + chalk100.dim(" moves to the previous slide.")
47186
47278
  );
47187
47279
  console.log();
47188
47280
  console.log(" " + sectionHeading("Shortcuts"));
@@ -47210,11 +47302,11 @@ function printHelp() {
47210
47302
  ];
47211
47303
  const maxW = Math.max(...shortcuts.map(([c]) => c.length)) + 2;
47212
47304
  for (const [cmd, desc] of shortcuts) {
47213
- console.log(` ${paint("accent", padRight(cmd, maxW))} ${chalk99.dim(desc)}`);
47305
+ console.log(` ${paint("accent", padRight(cmd, maxW))} ${chalk100.dim(desc)}`);
47214
47306
  }
47215
47307
  console.log();
47216
47308
  console.log(" " + sectionHeading("Teach NTRP"));
47217
- console.log(" " + chalk99.dim("NTRP learns your business over time. There are three ways to teach it:"));
47309
+ console.log(" " + chalk100.dim("NTRP learns your business over time. There are three ways to teach it:"));
47218
47310
  const teach = [
47219
47311
  ["/remember <fact>", "Store a fact, a decision, or a preference"],
47220
47312
  ["/recall [topic]", "Show what NTRP stores about your business"],
@@ -47223,13 +47315,13 @@ function printHelp() {
47223
47315
  ];
47224
47316
  const teachMaxW = Math.max(...teach.map(([c]) => c.length)) + 2;
47225
47317
  for (const [cmd, desc] of teach) {
47226
- console.log(` ${paint("accent", padRight(cmd, teachMaxW))} ${chalk99.dim(desc)}`);
47318
+ console.log(` ${paint("accent", padRight(cmd, teachMaxW))} ${chalk100.dim(desc)}`);
47227
47319
  }
47228
- console.log(" " + chalk99.dim("When a key is connected, NTRP stores a small number of facts when you close a session."));
47320
+ console.log(" " + chalk100.dim("When a key is connected, NTRP stores a small number of facts when you close a session."));
47229
47321
  console.log();
47230
- console.log(" " + chalk99.dim("Factory reset: type ") + paint("accent", "/scratch") + chalk99.dim("."));
47322
+ console.log(" " + chalk100.dim("Factory reset: type ") + paint("accent", "/scratch") + chalk100.dim("."));
47231
47323
  console.log();
47232
- console.log(" " + chalk99.dim("These commands also work: ") + paint("accent", "/new") + chalk99.dim(", ") + paint("accent", "/diagnose") + chalk99.dim(", ") + paint("accent", "/metrics") + chalk99.dim(", ") + paint("accent", "/session") + chalk99.dim("."));
47324
+ console.log(" " + chalk100.dim("These commands also work: ") + paint("accent", "/new") + chalk100.dim(", ") + paint("accent", "/diagnose") + chalk100.dim(", ") + paint("accent", "/metrics") + chalk100.dim(", ") + paint("accent", "/session") + chalk100.dim("."));
47233
47325
  console.log();
47234
47326
  }
47235
47327
  var REPL_BUILTINS, ANSI_PATTERN, GOODBYES, GHOST_HINTS, ghostHintTurn, activeGhostHint, suggestionPainted;
@@ -47329,7 +47421,7 @@ init_errors();
47329
47421
  init_diagnostics();
47330
47422
  init_types();
47331
47423
  init_version();
47332
- import chalk100 from "chalk";
47424
+ import chalk101 from "chalk";
47333
47425
  var VERSION = getInstalledVersion();
47334
47426
  function exitIfVersionFlag(argv) {
47335
47427
  const rest = argv.slice(2).filter((a) => a === "--version" || a === "-v");
@@ -47367,7 +47459,7 @@ async function main() {
47367
47459
  debug: args.globals.debug
47368
47460
  });
47369
47461
  if (!ctx.execution.color) {
47370
- chalk100.level = 0;
47462
+ chalk101.level = 0;
47371
47463
  }
47372
47464
  fatalReporting = {
47373
47465
  command: firstToken(args.input) || "ntrp",
@@ -47384,16 +47476,16 @@ async function main() {
47384
47476
  if (isStructuredOutput(ctx.execution)) {
47385
47477
  emitError(cmd || "ntrp", new NtrpError("license_invalid", lic.message, 3 /* Auth */));
47386
47478
  }
47387
- console.error(chalk100.red(`
47479
+ console.error(chalk101.red(`
47388
47480
  ${lic.message}`));
47389
- console.error(chalk100.dim(" Trial's over \u2014 /upgrade and paste your key.\n"));
47481
+ console.error(chalk101.dim(" Trial's over \u2014 /upgrade and paste your key.\n"));
47390
47482
  process.exit(1);
47391
47483
  }
47392
47484
  }
47393
47485
  const PROFILE_HINT_SKIP = /* @__PURE__ */ new Set(["onboard", "setup", "config", "connect", "activate", "help", "home", "exit", "quit", "clear", "profile", "progress", "deepdive", "tour", "settings", "voice", "logs"]);
47394
47486
  if (!isProfileConfigured() && !PROFILE_HINT_SKIP.has(cmd) && !ctx.execution.quiet) {
47395
47487
  console.error(
47396
- " " + chalk100.dim("Tip: run ") + paint("accent", "ntrp") + chalk100.dim(" interactively to set up your company profile for richer answers.")
47488
+ " " + chalk101.dim("Tip: run ") + paint("accent", "ntrp") + chalk101.dim(" interactively to set up your company profile for richer answers.")
47397
47489
  );
47398
47490
  }
47399
47491
  const result = await dispatch(args.input, ctx);
@@ -47405,12 +47497,12 @@ async function main() {
47405
47497
  }
47406
47498
  if (result.suggestion) {
47407
47499
  console.error(
47408
- chalk100.red(` Unknown command: ${result.token}.`) + chalk100.dim(" Did you mean ") + paint("accent", result.suggestion) + chalk100.dim("?")
47500
+ chalk101.red(` Unknown command: ${result.token}.`) + chalk101.dim(" Did you mean ") + paint("accent", result.suggestion) + chalk101.dim("?")
47409
47501
  );
47410
47502
  } else {
47411
- console.error(chalk100.red(` Unknown command: ${result.token}`));
47503
+ console.error(chalk101.red(` Unknown command: ${result.token}`));
47412
47504
  }
47413
- console.error(chalk100.dim(" Run 'ntrp' for the interactive prompt."));
47505
+ console.error(chalk101.dim(" Run 'ntrp' for the interactive prompt."));
47414
47506
  process.exit(1);
47415
47507
  break;
47416
47508
  case "help":
@@ -47463,7 +47555,7 @@ async function main() {
47463
47555
  if (justUpdated) {
47464
47556
  clearTerminalHome();
47465
47557
  console.log();
47466
- console.log(" " + paint("accent", "\u2713") + " " + chalk100.dim(`Now running v${justUpdated.to}`));
47558
+ console.log(" " + paint("accent", "\u2713") + " " + chalk101.dim(`Now running v${justUpdated.to}`));
47467
47559
  }
47468
47560
  await printWelcome2(ctx, VERSION);
47469
47561
  await runRepl(ctx, VERSION);
@@ -47477,9 +47569,9 @@ async function die(err, scope) {
47477
47569
  if (fatalReporting.structured) {
47478
47570
  emitError(fatalReporting.command, err);
47479
47571
  }
47480
- console.error(chalk100.red(` ${describeError(err)}`));
47572
+ console.error(chalk101.red(` ${describeError(err)}`));
47481
47573
  if (!(err instanceof NtrpError) && err instanceof Error && err.stack) {
47482
- console.error(chalk100.dim(err.stack.split("\n").slice(1).join("\n")));
47574
+ console.error(chalk101.dim(err.stack.split("\n").slice(1).join("\n")));
47483
47575
  }
47484
47576
  process.exit(err instanceof NtrpError ? err.exitCode : 1 /* RuntimeError */);
47485
47577
  }
@@ -1088,7 +1088,7 @@ import chalk3 from "chalk";
1088
1088
  function printDeepdiveHint(metricId, label) {
1089
1089
  const name = label ?? metricId;
1090
1090
  console.log(
1091
- " " + chalk3.dim(`Ask what ${name.toLowerCase()} means \u2014 or `) + paint("accent", `/tour ${metricId}`) + chalk3.dim(" for the card")
1091
+ " " + chalk3.dim(`Ask what ${name.toLowerCase()} means \u2014 or `) + paint("accent", `/tour ${metricId}`) + chalk3.dim(" if you want the card.")
1092
1092
  );
1093
1093
  console.log();
1094
1094
  }
@@ -12978,7 +12978,24 @@ function listMetricExplainers(kind) {
12978
12978
  if (!kind) return METRIC_DEFINITIONS.slice();
12979
12979
  return METRIC_DEFINITIONS.filter((m) => m.kind === kind);
12980
12980
  }
12981
- var VITALS, SAAS, METRIC_DEFINITIONS, BY_ID, ALIAS_INDEX, SAAS_METRIC_IDS;
12981
+ function buildVitalSignsPromptBlock() {
12982
+ return VITAL_IDS.map((id) => {
12983
+ const m = getMetricExplainer(id);
12984
+ if (!m) {
12985
+ throw new Error(`buildVitalSignsPromptBlock: missing explainer for ${id}`);
12986
+ }
12987
+ if (!m.dollar_label) {
12988
+ throw new Error(`buildVitalSignsPromptBlock: missing dollar_label for ${id}`);
12989
+ }
12990
+ return [
12991
+ `- ${m.id}: ${m.tagline}`,
12992
+ ` Teach: ${m.meaning}`,
12993
+ ` Expert read: ${m.expert_read}`,
12994
+ ` Dollar label: ${m.dollar_label}`
12995
+ ].join("\n");
12996
+ }).join("\n");
12997
+ }
12998
+ var VITALS, SAAS, METRIC_DEFINITIONS, BY_ID, ALIAS_INDEX, VITAL_IDS, SAAS_METRIC_IDS;
12982
12999
  var init_metric_definitions = __esm({
12983
13000
  "src/data/metric-definitions.ts"() {
12984
13001
  "use strict";
@@ -13772,6 +13789,13 @@ var init_metric_definitions = __esm({
13772
13789
  idx.set("thread-depth", "thread_depth");
13773
13790
  return idx;
13774
13791
  })();
13792
+ VITAL_IDS = [
13793
+ "freshness",
13794
+ "flow_rate",
13795
+ "drop_rate",
13796
+ "signal_to_noise",
13797
+ "thread_depth"
13798
+ ];
13775
13799
  SAAS_METRIC_IDS = SAAS.map((m) => m.id);
13776
13800
  }
13777
13801
  });
@@ -15288,6 +15312,7 @@ var init_prompt_parts = __esm({
15288
15312
  init_profile();
15289
15313
  init_store();
15290
15314
  init_gtm_counsel();
15315
+ init_metric_definitions();
15291
15316
  init_playbook();
15292
15317
  init_play_outcomes();
15293
15318
  init_registry();
@@ -15324,16 +15349,7 @@ Restraint matters: NTRP is a stethoscope, not a surgeon. Observe, connect, and r
15324
15349
  - Observe, connect, recommend \u2014 never execute CRM changes, send email, or claim an action was taken unless a tool result in this conversation confirms it.
15325
15350
  - Weak or empty tool result: vary the arguments or approach once before concluding; if it's still empty, say what you'd need rather than filling the gap with plausible-sounding numbers.
15326
15351
  - Never fabricate CRM records, people, companies, or dollar amounts.`;
15327
- VITAL_SIGNS_BLOCK = `- freshness: Data recency. Low = stale contacts, zombie deals. Dollar value = pipeline at risk from stale accounts.
15328
- Expert read: cut by owner and by stage first \u2014 freshness reds concentrate on people or process, rarely evenly. In a long-cycle enterprise motion 30 quiet days can be normal cadence; in a velocity motion it's a dead deal. A sudden cliff usually means a broken integration or a departed rep, not gradual decay. False positive to check: bulk-imported records nobody has touched yet.
15329
- - flow_rate: Deal velocity. Low = stuck pipeline, slow progression. Dollar value = amount stuck in pipeline.
15330
- Expert read: cut by stage-age, not just deal-age \u2014 find the stage where deals go to die (usually one). Compare stuck-deal age to this company's own median cycle, not a generic norm. Stuck + past-due close dates together signal happy-ears forecasting, a credibility problem before it's a revenue problem.
15331
- - drop_rate: Handoff retention. Low = leads vanishing between marketing and sales. Dollar value = estimated lost revenue at handoff.
15332
- Expert read: this is almost always a systems failure \u2014 routing rules, unassigned territories, dead rep queues, or a sync gap between marketing and CRM \u2014 not lazy reps. First cut by lead source; the leak usually concentrates in one or two sources. The cheapest pipeline this business can buy is the leads it already paid for.
15333
- - signal_to_noise: Activity efficiency. Low = effort aimed at dead ends. Dollar value = cost of misdirected effort.
15334
- Expert read: cut by rep and by account status \u2014 noise usually means reps fishing in the pond they can see (dead accounts they know) because targeting and account lists are stale. Persistent noise is a coverage-model problem, not a coaching problem. Check whether activity is logged against closed or unlinked records \u2014 often a hygiene artifact.
15335
- - thread_depth: Deal resilience. Low = single-threaded deals, fragile pipeline. Dollar value = amount in single-threaded deals.
15336
- Expert read: weight by deal size \u2014 one single-threaded mega-deal outweighs ten small ones. Single-threading late in the cycle is far more dangerous than early. In enterprise motions, thread depth is a leading indicator of slipped quarters: champions change jobs, and there's no second door in.`;
15352
+ VITAL_SIGNS_BLOCK = buildVitalSignsPromptBlock();
15337
15353
  PLAYBOOK_BLOCK = `- "Multi-Thread Your Deals" (id: multi-thread-deals) \u2014 when thread_depth is low
15338
15354
  - "Clean Dead Pipeline" (id: clean-dead-pipeline) \u2014 when freshness is low
15339
15355
  - "Fix the Handoff Gap" (id: fix-handoff-gap) \u2014 when drop_rate is high and the source\u2192owner path is unknown
@@ -24654,12 +24670,9 @@ var init_ghost_hints = __esm({
24654
24670
  init_suggested_asks();
24655
24671
  PHASE_GHOST_HINTS = {
24656
24672
  orient: [
24657
- 'try "pipeline health"',
24658
24673
  'try "how healthy is the pipeline?"',
24659
- 'try "what should I do next?"',
24660
- 'try "is our retention real for the board?"',
24661
- 'try "what is the most expensive problem to solve?"',
24662
- 'try "board deck on Q3"'
24674
+ 'try "what does freshness mean?"',
24675
+ 'try "what should I do next?"'
24663
24676
  ],
24664
24677
  awaiting_data: [
24665
24678
  'try "use demo data"',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sonnechasser/ntrp",
3
- "version": "2.3.2",
3
+ "version": "2.4.1",
4
4
  "description": "GTM Health Diagnostic CLI — local pipeline analysis tool",
5
5
  "homepage": "https://ntrp.sonnechasser.com",
6
6
  "repository": {