@sonnechasser/ntrp 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +77 -11
- package/dist/index.js.map +1 -1
- package/dist/investigation/verbosity-cli.js +1007 -198
- package/dist/investigation/verbosity-cli.js.map +1 -1
- package/dist/mcp/server.js +1992 -1133
- package/dist/mcp/server.js.map +1 -1
- package/dist/whimsy/time-bank-smoke.js +255 -199
- package/dist/whimsy/time-bank-smoke.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -13580,12 +13580,41 @@ function buildPlaybookBlock() {
|
|
|
13580
13580
|
Learned plays (added from this team's experience and ingested case studies \u2014 recommend these when they fit):
|
|
13581
13581
|
${learned}`;
|
|
13582
13582
|
}
|
|
13583
|
-
|
|
13583
|
+
function buildCommandCatalogBlock() {
|
|
13584
|
+
const GROUP_ANALYSIS = "Analysis & data";
|
|
13585
|
+
const GROUP_SESSION = "Session, memory & outputs";
|
|
13586
|
+
const GROUP_SETTINGS = "Settings & providers";
|
|
13587
|
+
const groupOrder = [GROUP_ANALYSIS, GROUP_SESSION, GROUP_SETTINGS];
|
|
13588
|
+
const groupFor = (section) => {
|
|
13589
|
+
if (section === "Hidden" || section === "Getting Started") return GROUP_ANALYSIS;
|
|
13590
|
+
if (section === "Settings") return GROUP_SETTINGS;
|
|
13591
|
+
return GROUP_SESSION;
|
|
13592
|
+
};
|
|
13593
|
+
const groups = new Map(groupOrder.map((label) => [label, []]));
|
|
13594
|
+
for (const meta of listWorkflows(true)) {
|
|
13595
|
+
if (meta.name === "ask") continue;
|
|
13596
|
+
if (meta.section === "Admin") continue;
|
|
13597
|
+
groups.get(groupFor(meta.section)).push(formatCatalogLine(meta));
|
|
13598
|
+
}
|
|
13599
|
+
groups.get(GROUP_SESSION).push(
|
|
13600
|
+
"- /help \u2014 Show the shortcut list",
|
|
13601
|
+
"- /home \u2014 Show the welcome dashboard and current session status"
|
|
13602
|
+
);
|
|
13603
|
+
return groupOrder.filter((label) => groups.get(label).length > 0).map((label) => `${label}:
|
|
13604
|
+
${groups.get(label).join("\n")}`).join("\n\n");
|
|
13605
|
+
}
|
|
13606
|
+
function formatCatalogLine(meta) {
|
|
13607
|
+
const args = meta.args?.trim() ? ` ${meta.args.trim()}` : "";
|
|
13608
|
+
const note = DESTRUCTIVE_COMMAND_NOTES[meta.name] ? ` (${DESTRUCTIVE_COMMAND_NOTES[meta.name]})` : "";
|
|
13609
|
+
return `- /${meta.name}${args} \u2014 ${meta.description}${note}`;
|
|
13610
|
+
}
|
|
13611
|
+
var ANALYST_INSTINCT_BLOCK, VITAL_SIGNS_BLOCK, PLAYBOOK_BLOCK, DESTRUCTIVE_COMMAND_NOTES, METRICS_BLOCK, FINDINGS_SCHEMA_BLOCK;
|
|
13584
13612
|
var init_prompt_parts = __esm({
|
|
13585
13613
|
"src/ai/prompt-parts.ts"() {
|
|
13586
13614
|
"use strict";
|
|
13587
13615
|
init_profile();
|
|
13588
13616
|
init_playbook();
|
|
13617
|
+
init_registry2();
|
|
13589
13618
|
ANALYST_INSTINCT_BLOCK = `A search box returns numbers; a world-class analyst returns insight. The instincts below are what separate the two. Bring them PROACTIVELY \u2014 surface the connection, the chain, and the priority without waiting to be asked, because the user often doesn't know to ask.
|
|
13590
13619
|
|
|
13591
13620
|
- ROOT CAUSE OVER SYMPTOM LIST. GTM problems are rarely independent \u2014 they're usually one failure wearing several masks. When two or more vital signs are red or yellow, your first instinct is to ask "is this the same underlying problem showing up in different places?" and, when it is, name the single cause. (Classic shape: a broken lead handoff starves reps of new pipeline \u2192 they work only what they can already see \u2192 everything else ages into stale, zombie deals \u2192 the forecast inflates with deals nobody is touching \u2192 the quarter is quietly at risk. One cause, four symptoms.)
|
|
@@ -13608,6 +13637,9 @@ Restraint matters: NTRP is a stethoscope, not a surgeon. Observe, connect, and r
|
|
|
13608
13637
|
- "Fix the Handoff Gap" (id: fix-handoff-gap) \u2014 when drop_rate is high
|
|
13609
13638
|
- "Retarget Misdirected Effort" (id: retarget-effort) \u2014 when signal_to_noise is low
|
|
13610
13639
|
- "Unstick the Pipeline" (id: unstick-pipeline) \u2014 when flow_rate is low`;
|
|
13640
|
+
DESTRUCTIVE_COMMAND_NOTES = {
|
|
13641
|
+
reset: "destructive \u2014 wipes all data, requires --force"
|
|
13642
|
+
};
|
|
13611
13643
|
METRICS_BLOCK = `Revenue metrics measure GTM output \u2014 the standard SaaS metrics:
|
|
13612
13644
|
- ARR: Total closed-won revenue. New ARR + Expansion ARR = growth; Churned + Contraction = leakage.
|
|
13613
13645
|
- NRR (Net Revenue Retention): >100% means growing from existing customers. Best-in-class: 110%+.
|
|
@@ -15584,15 +15616,18 @@ function inferHandoffTarget(input) {
|
|
|
15584
15616
|
return "plan";
|
|
15585
15617
|
}
|
|
15586
15618
|
function isShipIntent(input) {
|
|
15587
|
-
|
|
15588
|
-
|
|
15589
|
-
);
|
|
15619
|
+
const line = input.trim();
|
|
15620
|
+
if (/\?\s*$/.test(line) || QUESTION_LEAD_RE.test(line)) return false;
|
|
15621
|
+
return SHIP_INTENT_RE.test(line);
|
|
15590
15622
|
}
|
|
15623
|
+
var QUESTION_LEAD_RE, SHIP_INTENT_RE;
|
|
15591
15624
|
var init_handoff_draft = __esm({
|
|
15592
15625
|
"src/conversation/handoff-draft.ts"() {
|
|
15593
15626
|
"use strict";
|
|
15594
15627
|
init_profile();
|
|
15595
15628
|
init_session_analysis();
|
|
15629
|
+
QUESTION_LEAD_RE = /^\s*(what|why|how|when|where|who|which|is|are|was|were|do|does|did|explain|tell me|help me understand)\b/i;
|
|
15630
|
+
SHIP_INTENT_RE = /\b(ship|export|deliver|write[- ]?up|board memo|action plan|turn (this|it|that) into|(draft|create|make|build|prepare|generate|send)\s+(me\s+)?(a\s+|the\s+)?hand[- ]?off|hand[- ]?off\s+(prompt|doc|document|plan))\b/i;
|
|
15596
15631
|
}
|
|
15597
15632
|
});
|
|
15598
15633
|
|
|
@@ -16154,6 +16189,16 @@ FORMATTING (brief mode \u2014 scannable, not chunky):
|
|
|
16154
16189
|
- No ### headings, no tables, no --- footer, no closing "want me to dig deeper?" question.
|
|
16155
16190
|
- Single-point answers can stay one sentence \u2014 don't force bullets when one line is enough.
|
|
16156
16191
|
`;
|
|
16192
|
+
const commandStyleRule = responseMode === "brief" ? '- Style in brief mode: a suggestion is at most ONE short trailing line after your answer (e.g. "`/segment compare enterprise smb` gives the full side-by-side.") \u2014 no heading, no footer.' : "- Style: weave the suggestion naturally into your close \u2014 one sentence with the exact invocation in `inline code`.";
|
|
16193
|
+
const commandSection = `PRESET COMMANDS (slash commands the user can type at the prompt \u2014 you may SUGGEST these; you have no ability to run them):
|
|
16194
|
+
${buildCommandCatalogBlock()}
|
|
16195
|
+
|
|
16196
|
+
COMMAND SUGGESTION RULES (suggest-only):
|
|
16197
|
+
- Evaluate whether the user's question overlaps a preset command's capability. Answer the question yourself first, from tools and context; suggest a command only when it adds capability beyond your answer \u2014 writing files, opening a wizard, running a heavier analysis, or changing settings.
|
|
16198
|
+
- If the message is primarily a request to DO what a command does (e.g. "export this to my notes"), say plainly that you don't execute commands and give the exact invocation to type, e.g. \`/handoff notes\`.
|
|
16199
|
+
- Never claim a command was run. Never invent flags \u2014 use only the documented arguments above. At most ONE command suggestion per answer; most answers need none.
|
|
16200
|
+
- Only suggest a command that can work right now given the session state you know (e.g. no \`/diagnose\` or \`/export\` before data or a diagnosis exists).
|
|
16201
|
+
${commandStyleRule}`;
|
|
16157
16202
|
const outputRules = responseMode === "brief" ? `OUTPUT RULES:
|
|
16158
16203
|
- Respond in plain text markdown (not JSON). Lead sentence + bullets when helpful \u2014 never a dense paragraph wall.
|
|
16159
16204
|
- Pull numbers from the completed session analysis or conversation history \u2014 never guess.
|
|
@@ -16177,6 +16222,8 @@ ${VITAL_SIGNS_BLOCK}
|
|
|
16177
16222
|
|
|
16178
16223
|
PLAYBOOK \u2014 recommend these plays when appropriate:
|
|
16179
16224
|
${buildPlaybookBlock()}
|
|
16225
|
+
|
|
16226
|
+
${commandSection}
|
|
16180
16227
|
${formattingSection}
|
|
16181
16228
|
${outputRules}`;
|
|
16182
16229
|
}
|
|
@@ -26633,10 +26680,10 @@ function randomGoodbye() {
|
|
|
26633
26680
|
return GOODBYES[Math.floor(Math.random() * GOODBYES.length)] ?? "Bye.";
|
|
26634
26681
|
}
|
|
26635
26682
|
function commandCompletionCandidates() {
|
|
26636
|
-
return [
|
|
26683
|
+
return [.../* @__PURE__ */ new Set([
|
|
26637
26684
|
...REPL_BUILTINS,
|
|
26638
|
-
...listCommandNames(
|
|
26639
|
-
];
|
|
26685
|
+
...listCommandNames(true).map((name) => `/${name}`)
|
|
26686
|
+
])];
|
|
26640
26687
|
}
|
|
26641
26688
|
function completeCommand(line) {
|
|
26642
26689
|
const firstToken2 = line.split(/\s/, 1)[0] ?? "";
|
|
@@ -26648,17 +26695,35 @@ function completeCommand(line) {
|
|
|
26648
26695
|
function inlineCommandSuggestion(line) {
|
|
26649
26696
|
if (!line.startsWith("/") || /\s/.test(line)) return null;
|
|
26650
26697
|
const matches = commandCompletionCandidates().filter((command) => command.startsWith(line));
|
|
26651
|
-
if (matches.length
|
|
26652
|
-
|
|
26698
|
+
if (matches.length === 0) return null;
|
|
26699
|
+
if (matches.length === 1) {
|
|
26700
|
+
return matches[0] === line ? null : matches[0].slice(line.length);
|
|
26701
|
+
}
|
|
26702
|
+
let common = matches[0];
|
|
26703
|
+
for (const match of matches) {
|
|
26704
|
+
let i = 0;
|
|
26705
|
+
while (i < common.length && i < match.length && common[i] === match[i]) i++;
|
|
26706
|
+
common = common.slice(0, i);
|
|
26707
|
+
}
|
|
26708
|
+
return common.length > line.length ? common.slice(line.length) : null;
|
|
26653
26709
|
}
|
|
26654
26710
|
function renderInlineSuggestion(rl, prompt) {
|
|
26655
26711
|
const line = rl.line;
|
|
26656
26712
|
const cursor = rl.cursor;
|
|
26657
26713
|
const suffix = cursor === line.length ? inlineCommandSuggestion(line) : null;
|
|
26714
|
+
const promptWidth = visibleLength(prompt);
|
|
26715
|
+
const columns = process.stdout.columns ?? 80;
|
|
26716
|
+
const fitsOneRow = promptWidth + line.length + (suffix?.length ?? 0) < columns;
|
|
26717
|
+
const shouldPaint = (suffix !== null || suggestionPainted) && fitsOneRow;
|
|
26718
|
+
if (!shouldPaint) {
|
|
26719
|
+
suggestionPainted = false;
|
|
26720
|
+
return;
|
|
26721
|
+
}
|
|
26722
|
+
suggestionPainted = suffix !== null;
|
|
26658
26723
|
clearLine2(process.stdout, 0);
|
|
26659
26724
|
cursorTo2(process.stdout, 0);
|
|
26660
26725
|
process.stdout.write(prompt + line + (suffix ? chalk68.dim(suffix) : ""));
|
|
26661
|
-
cursorTo2(process.stdout,
|
|
26726
|
+
cursorTo2(process.stdout, promptWidth + cursor);
|
|
26662
26727
|
}
|
|
26663
26728
|
function appendTurnLine(current, promptLabel, currentSummary) {
|
|
26664
26729
|
const currentLine = currentSummary ? `${promptLabel} ${current} ${chalk68.white("\u2192")} ${currentSummary}` : `${promptLabel} ${current}`;
|
|
@@ -26885,7 +26950,7 @@ function printHelp() {
|
|
|
26885
26950
|
console.log(" " + chalk68.dim("Power-user commands (") + paint("accent", "/new") + chalk68.dim(", ") + paint("accent", "/diagnose") + chalk68.dim(", ") + paint("accent", "/metrics") + chalk68.dim(") remain available."));
|
|
26886
26951
|
console.log();
|
|
26887
26952
|
}
|
|
26888
|
-
var REPL_BUILTINS, ANSI_PATTERN, GOODBYES;
|
|
26953
|
+
var REPL_BUILTINS, ANSI_PATTERN, GOODBYES, suggestionPainted;
|
|
26889
26954
|
var init_repl = __esm({
|
|
26890
26955
|
"src/cli/repl.ts"() {
|
|
26891
26956
|
"use strict";
|
|
@@ -26945,6 +27010,7 @@ var init_repl = __esm({
|
|
|
26945
27010
|
"May your pipeline stay hydrated.",
|
|
26946
27011
|
"Don't let the zombie deals bite."
|
|
26947
27012
|
];
|
|
27013
|
+
suggestionPainted = false;
|
|
26948
27014
|
}
|
|
26949
27015
|
});
|
|
26950
27016
|
|