@sonnechasser/ntrp 2.1.11 → 2.1.12
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 +254 -115
- package/dist/mcp/server.js +168 -83
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1719,8 +1719,10 @@ var init_prefs = __esm({
|
|
|
1719
1719
|
// src/voice/copy.ts
|
|
1720
1720
|
var copy_exports = {};
|
|
1721
1721
|
__export(copy_exports, {
|
|
1722
|
+
EXPORT_PICKUP_PHRASE: () => EXPORT_PICKUP_PHRASE,
|
|
1722
1723
|
voiceAuthFailureAlert: () => voiceAuthFailureAlert,
|
|
1723
1724
|
voiceAuthFailureHint: () => voiceAuthFailureHint,
|
|
1725
|
+
voiceExportPickupNudge: () => voiceExportPickupNudge,
|
|
1724
1726
|
voiceGapLoadCta: () => voiceGapLoadCta,
|
|
1725
1727
|
voiceGapReadyCta: () => voiceGapReadyCta,
|
|
1726
1728
|
voiceHandoffAddendum: () => voiceHandoffAddendum,
|
|
@@ -1873,6 +1875,34 @@ function voiceHealthGloss(status, prefs) {
|
|
|
1873
1875
|
}
|
|
1874
1876
|
});
|
|
1875
1877
|
}
|
|
1878
|
+
function voiceExportPickupNudge(input, prefs) {
|
|
1879
|
+
const v = voice(prefs);
|
|
1880
|
+
const phrase = EXPORT_PICKUP_PHRASE;
|
|
1881
|
+
if (input.inboxReady) {
|
|
1882
|
+
return pick(v, {
|
|
1883
|
+
robotic: `Open your desktop AI. Tell it to ${phrase}.`,
|
|
1884
|
+
composed: `Open your desktop AI and tell it to ${phrase}.`,
|
|
1885
|
+
casual: `This terminal is not your AI. Open it and tell it to ${phrase}.`,
|
|
1886
|
+
loose: {
|
|
1887
|
+
light: `Written. Open your desktop AI and tell it to ${phrase}.`,
|
|
1888
|
+
medium: `This CLI cannot see your AI. Open it. Tell it to ${phrase}.`,
|
|
1889
|
+
dark: `The file is on disk. Your AI is not in this window. Open it and ${phrase}.`,
|
|
1890
|
+
heavy: `NTRP wrote it. This window is not your AI. Open the desktop app and ${phrase}.`
|
|
1891
|
+
}
|
|
1892
|
+
});
|
|
1893
|
+
}
|
|
1894
|
+
return pick(v, {
|
|
1895
|
+
robotic: `Your desktop AI cannot see this folder. Type /inbox set, then tell that AI to ${phrase}.`,
|
|
1896
|
+
composed: `These files are on disk. Set a pickup folder (/inbox set), then tell your desktop AI to ${phrase}.`,
|
|
1897
|
+
casual: `Your AI cannot see this folder. Type /inbox set, then tell it to ${phrase}.`,
|
|
1898
|
+
loose: {
|
|
1899
|
+
light: `Your AI cannot see this folder yet. Type /inbox set, then tell it to ${phrase}.`,
|
|
1900
|
+
medium: `This folder is invisible to your AI. Type /inbox set, then tell it to ${phrase}.`,
|
|
1901
|
+
dark: `Your AI cannot see this terminal. Type /inbox set, then ${phrase}.`,
|
|
1902
|
+
heavy: `This window is not your AI. Type /inbox set, then ${phrase}.`
|
|
1903
|
+
}
|
|
1904
|
+
});
|
|
1905
|
+
}
|
|
1876
1906
|
function voiceHandoffAddendum(prefs) {
|
|
1877
1907
|
const v = voice(prefs);
|
|
1878
1908
|
return [
|
|
@@ -1887,11 +1917,13 @@ function pick(prefs, map) {
|
|
|
1887
1917
|
if (typeof entry === "string") return entry;
|
|
1888
1918
|
return entry[prefs.roast];
|
|
1889
1919
|
}
|
|
1920
|
+
var EXPORT_PICKUP_PHRASE;
|
|
1890
1921
|
var init_copy = __esm({
|
|
1891
1922
|
"src/voice/copy.ts"() {
|
|
1892
1923
|
"use strict";
|
|
1893
1924
|
init_catalog();
|
|
1894
1925
|
init_prefs();
|
|
1926
|
+
EXPORT_PICKUP_PHRASE = "pick up the latest NTRP handoff";
|
|
1895
1927
|
}
|
|
1896
1928
|
});
|
|
1897
1929
|
|
|
@@ -2925,6 +2957,7 @@ __export(handoff_skill_exports, {
|
|
|
2925
2957
|
persistHandoffSkillFiles: () => persistHandoffSkillFiles,
|
|
2926
2958
|
persistStandingSkill: () => persistStandingSkill,
|
|
2927
2959
|
pickupContextFromEvent: () => pickupContextFromEvent,
|
|
2960
|
+
printExportPickupNudge: () => printExportPickupNudge,
|
|
2928
2961
|
printHandoffDelivered: () => printHandoffDelivered,
|
|
2929
2962
|
printStandingSkill: () => printStandingSkill
|
|
2930
2963
|
});
|
|
@@ -3163,11 +3196,14 @@ function maybePrintAiInboxNudge() {
|
|
|
3163
3196
|
)
|
|
3164
3197
|
);
|
|
3165
3198
|
}
|
|
3199
|
+
function printExportPickupNudge(opts) {
|
|
3200
|
+
console.log(" " + chalk7.dim(voiceExportPickupNudge(opts)));
|
|
3201
|
+
}
|
|
3166
3202
|
function printHandoffDelivered(event, opts = {}) {
|
|
3167
3203
|
persistHandoffSkillFiles(event);
|
|
3168
3204
|
console.log();
|
|
3169
3205
|
console.log(" " + paint("accent", `Handoff ready (${kindLabel(event.kind)})`));
|
|
3170
|
-
|
|
3206
|
+
printExportPickupNudge({ inboxReady: Boolean(event.inbox_path) });
|
|
3171
3207
|
if (opts.body) {
|
|
3172
3208
|
console.log(" " + chalk7.dim("File body (--print)"));
|
|
3173
3209
|
printPlainBlock(opts.body);
|
|
@@ -3199,6 +3235,7 @@ var init_handoff_skill = __esm({
|
|
|
3199
3235
|
init_store();
|
|
3200
3236
|
init_theme();
|
|
3201
3237
|
init_export_kinds();
|
|
3238
|
+
init_copy();
|
|
3202
3239
|
STANDING_SKILL_NAME = "SKILL.md";
|
|
3203
3240
|
ARCHIVE_PICKUP_NAME = "pickup.md";
|
|
3204
3241
|
INBOX_PICKUP_NAME = "latest-pickup.md";
|
|
@@ -10723,7 +10760,7 @@ ${strategy.objective}
|
|
|
10723
10760
|
` : "";
|
|
10724
10761
|
const workstreamSection = strategy.workstreams.length > 0 ? `
|
|
10725
10762
|
## Workstreams
|
|
10726
|
-
${strategy.workstreams.map(
|
|
10763
|
+
${strategy.workstreams.map(formatWorkstreamMarkdown).join("\n")}
|
|
10727
10764
|
` : "";
|
|
10728
10765
|
const constraintsSection = filterOperatorLines(strategy.constraints).length > 0 ? `
|
|
10729
10766
|
## Constraints
|
|
@@ -10779,7 +10816,7 @@ ${strategy.objective}
|
|
|
10779
10816
|
` : "";
|
|
10780
10817
|
const workstreamSection = strategy.workstreams.length > 0 ? `
|
|
10781
10818
|
## Workstreams
|
|
10782
|
-
${strategy.workstreams.map(
|
|
10819
|
+
${strategy.workstreams.map(formatWorkstreamMarkdown).join("\n")}
|
|
10783
10820
|
` : "";
|
|
10784
10821
|
const assumptions = filterOperatorLines(strategy.assumptions);
|
|
10785
10822
|
const assumptionsSection = assumptions.length > 0 ? `
|
|
@@ -10826,7 +10863,7 @@ ${frontmatter}
|
|
|
10826
10863
|
].filter((p) => p != null && String(p).length > 0);
|
|
10827
10864
|
return parts.join("\n\n") + "\n";
|
|
10828
10865
|
}
|
|
10829
|
-
function
|
|
10866
|
+
function formatWorkstreamMarkdown(ws) {
|
|
10830
10867
|
const lines = [];
|
|
10831
10868
|
lines.push(`### ${ws.order}. ${ws.title}`);
|
|
10832
10869
|
lines.push(`- Problem: ${ws.problem}`);
|
|
@@ -12189,6 +12226,7 @@ function resetContextForSwitch(ctx, opts) {
|
|
|
12189
12226
|
ctx.thinkState = opts.thinkState;
|
|
12190
12227
|
ctx.pendingAsk = opts.pendingAsk;
|
|
12191
12228
|
ctx.lastCraftJobId = opts.lastCraftJobId;
|
|
12229
|
+
ctx.lastStrategyBrief = void 0;
|
|
12192
12230
|
ctx.gapAudit = void 0;
|
|
12193
12231
|
ctx.deliverIntent = false;
|
|
12194
12232
|
ctx.computeInProgress = false;
|
|
@@ -14864,6 +14902,8 @@ var init_guide_slides = __esm({
|
|
|
14864
14902
|
"",
|
|
14865
14903
|
"Hit Enter by accident on \u23CE yes? Type b or back \u2014 that rewinds to the focus card. The same word leaves a strategy or think overlay. It does not unload demo data or undo compute; /scratch or a new session is the blunt reset.",
|
|
14866
14904
|
"",
|
|
14905
|
+
"After a strategy brief, the terminal shows the call, the exams, the next date, and what ships. Type more or expand for the full plan. The library and handoff files already hold every step.",
|
|
14906
|
+
"",
|
|
14867
14907
|
"Empty dataset? Load a sample with \u23CE use demo data, paste a CSV path, or /ingest. When the gap card says the formulas can compute, \u23CE go ahead runs the local math.",
|
|
14868
14908
|
"",
|
|
14869
14909
|
"Vital signs and SaaS metrics compute without an AI key. Every score that has a dollar translation shows it \u2014 that's the point of the stethoscope."
|
|
@@ -14872,7 +14912,7 @@ var init_guide_slides = __esm({
|
|
|
14872
14912
|
"Power-user slash commands still work. They stay hidden from /help: /new, /diagnose, /metrics, /ingest, /session.",
|
|
14873
14913
|
'"use demo data" loads a fitted sample book. Company profile is optional. In scripts, /demo --no-profile.',
|
|
14874
14914
|
'After compute, the prompt returns to \u203A. Brief is the default depth; type "go deep" for the long read.',
|
|
14875
|
-
"/home shows phase status. /help lists conversation shortcuts and the Keys legend (\u23CE, b/back, cancel)."
|
|
14915
|
+
"/home shows phase status. /help lists conversation shortcuts and the Keys legend (\u23CE, b/back, more/expand, cancel)."
|
|
14876
14916
|
]
|
|
14877
14917
|
};
|
|
14878
14918
|
ASK = {
|
|
@@ -14918,7 +14958,7 @@ var init_guide_slides = __esm({
|
|
|
14918
14958
|
lines: [
|
|
14919
14959
|
'We think of handoff as a quiet bridge: NTRP writes a board deck or brief into a folder you choose; your desktop AI (Claude, ChatGPT, Cursor, \u2026) opens it. You teach that AI a standing finder once \u2014 then later you just say "pick up the latest NTRP handoff."',
|
|
14920
14960
|
"",
|
|
14921
|
-
'"ship a board deck" or /handoff lands files in ~/Documents/ntrp-inbox by default (/inbox set to change). During demo or company setup \u2014 or anytime \u2014 /inbox skill prints the finder to paste once. After that, each
|
|
14961
|
+
'"ship a board deck" or /handoff lands files in ~/Documents/ntrp-inbox by default (/inbox set to change). During demo or company setup \u2014 or anytime \u2014 /inbox skill prints the finder to paste once. After that, each write prints "Handoff ready" without a paste block, then tells you to leave this terminal and pick up the latest NTRP handoff in your desktop AI.',
|
|
14922
14962
|
"",
|
|
14923
14963
|
"Skipped earlier? We ask once when you load your own data. Or /inbox set ~/Documents/ntrp-inbox, then /inbox skill. /handoff skill reprints the same finder."
|
|
14924
14964
|
],
|
|
@@ -14948,6 +14988,8 @@ var init_guide_slides = __esm({
|
|
|
14948
14988
|
"",
|
|
14949
14989
|
"At the confirm card, \u23CE yes builds that plan once. Type keep going to keep working until the plan is ready \u2014 the same armed-Enter pattern as use demo data and go ahead. If you see Best so far, the prompt returns to \u203A and \u23CE keep going continues. Plan ready? Type /strategy review later to check milestones against new vitals.",
|
|
14950
14990
|
"",
|
|
14991
|
+
"The printed brief is short on purpose: the call, the exams, the next date, and what ships. Type more (or expand) for the full plan. The library and handoff files already hold every step.",
|
|
14992
|
+
"",
|
|
14951
14993
|
"When a vital is red, /playbook names a matching play \u2014 and outcomes from reviews annotate the catalog with what actually hit here. /remember stores a durable fact; /rate bad <reason> writes a calibration. Optional ~/.ntrp/ANALYST.md is standing voice and priorities (it never overrides safety rules).",
|
|
14952
14994
|
"",
|
|
14953
14995
|
"Handy later: /sessions show, /session <id> pickup, /end (transcript + brief), /home, /progress, /help."
|
|
@@ -30537,20 +30579,7 @@ function renderCraftHandoffMarkdown(opts) {
|
|
|
30537
30579
|
lines.push("## Workstreams");
|
|
30538
30580
|
lines.push("");
|
|
30539
30581
|
for (const ws of plan.workstreams) {
|
|
30540
|
-
lines.push(
|
|
30541
|
-
lines.push("");
|
|
30542
|
-
lines.push(`- Problem: ${ws.problem}`);
|
|
30543
|
-
if (ws.rationale && !isGenericWorkstreamRationale(ws.rationale)) {
|
|
30544
|
-
lines.push(`- Why this order: ${ws.rationale}`);
|
|
30545
|
-
}
|
|
30546
|
-
if (ws.actions[0]) lines.push(`- First action (48h): ${ws.actions[0]}`);
|
|
30547
|
-
lines.push(`- Effort: ~${Math.round(ws.effort_hours)} team-hours`);
|
|
30548
|
-
lines.push(
|
|
30549
|
-
`- Exam: ${ws.expected_outcome.metric} ${ws.expected_outcome.baseline} \u2192 ${ws.expected_outcome.target_range} by ${ws.expected_outcome.check_date} (${ws.expected_outcome.measured_by})`
|
|
30550
|
-
);
|
|
30551
|
-
lines.push(
|
|
30552
|
-
`- Contingency: if ${ws.contingency.trigger} (check ${ws.contingency.trigger_check_date}) \u2192 ${ws.contingency.fallback}`
|
|
30553
|
-
);
|
|
30582
|
+
lines.push(formatWorkstreamMarkdown(ws).trimEnd());
|
|
30554
30583
|
lines.push("");
|
|
30555
30584
|
}
|
|
30556
30585
|
if (opts.roundtableDigest) {
|
|
@@ -30830,93 +30859,183 @@ var init_llm_attribution = __esm({
|
|
|
30830
30859
|
|
|
30831
30860
|
// src/output/strategy-brief.ts
|
|
30832
30861
|
import chalk24 from "chalk";
|
|
30833
|
-
function
|
|
30862
|
+
function collectWrapped(lines, text, width, prefix = INDENT, style) {
|
|
30834
30863
|
for (const line of wrapWords(text, width)) {
|
|
30835
|
-
|
|
30864
|
+
lines.push(prefix + (style ? style(line) : line));
|
|
30836
30865
|
}
|
|
30837
30866
|
}
|
|
30838
|
-
function outcomeLine(outcome) {
|
|
30839
|
-
|
|
30867
|
+
function outcomeLine(outcome, dateStyle) {
|
|
30868
|
+
const by = dateStyle === "accent" ? paint("accent", `by ${outcome.check_date}`) : chalk24.dim(`by ${outcome.check_date}`);
|
|
30869
|
+
return `${chalk24.bold(outcome.metric)}: ${outcome.baseline} ${chalk24.dim("\u2192")} ${chalk24.bold(outcome.target_range)} ${by}`;
|
|
30870
|
+
}
|
|
30871
|
+
function soonestByDue(items) {
|
|
30872
|
+
if (items.length === 0) return void 0;
|
|
30873
|
+
return [...items].sort((a, b) => a.due.localeCompare(b.due) || 0)[0];
|
|
30874
|
+
}
|
|
30875
|
+
function altitudeLine(text) {
|
|
30876
|
+
const sentence = findingHeadline(text) || text.trim();
|
|
30877
|
+
return truncateVisible(sentence, FOH_PROSE_MAX);
|
|
30878
|
+
}
|
|
30879
|
+
function coverageLine(plan, stats) {
|
|
30880
|
+
const totalHours = plan.workstreams.reduce((sum, ws) => sum + ws.effort_hours, 0);
|
|
30881
|
+
const hours = `~${Math.round(totalHours)} total team hours across ${plan.workstreams.length} workstream${plan.workstreams.length === 1 ? "" : "s"}`;
|
|
30882
|
+
if (stats.total_targets <= 0) return chalk24.dim(hours);
|
|
30883
|
+
const coverage = `${stats.measurable_targets} of ${stats.total_targets} targets can be measured with current data`;
|
|
30884
|
+
const coverageStyled = stats.measurable_targets === stats.total_targets ? paint("success", coverage) : chalk24.hex("#eab308")(coverage);
|
|
30885
|
+
return `${coverageStyled}${chalk24.dim(` \xB7 ${hours}`)}`;
|
|
30886
|
+
}
|
|
30887
|
+
function renderFohWorkstream(ws, width) {
|
|
30888
|
+
const lines = [];
|
|
30889
|
+
lines.push(`${INDENT}${paint("accent", `${ws.order}.`)} ${chalk24.bold(ws.title)}`);
|
|
30890
|
+
lines.push(`${INDENT} ${outcomeLine(ws.expected_outcome, "accent")}`);
|
|
30891
|
+
const next = soonestByDue(ws.milestones);
|
|
30892
|
+
if (next) {
|
|
30893
|
+
lines.push(`${INDENT} Next ${paint("accent", next.due)} ${next.label}`);
|
|
30894
|
+
}
|
|
30895
|
+
const ship = soonestByDue(ws.deliverables);
|
|
30896
|
+
if (ship) {
|
|
30897
|
+
lines.push(`${INDENT} Ship ${paint("accent", ship.due)} ${ship.label}`);
|
|
30898
|
+
}
|
|
30899
|
+
lines.push("");
|
|
30900
|
+
return lines;
|
|
30840
30901
|
}
|
|
30841
|
-
function
|
|
30842
|
-
|
|
30843
|
-
|
|
30844
|
-
|
|
30902
|
+
function renderBohWorkstream(ws, width) {
|
|
30903
|
+
const lines = [];
|
|
30904
|
+
lines.push(`${INDENT}${paint("accent", `${ws.order}.`)} ${chalk24.bold(ws.title)}`);
|
|
30905
|
+
collectWrapped(lines, ws.problem, width - 5, INDENT + " ", (s) => chalk24.dim(s));
|
|
30906
|
+
lines.push(`${INDENT} ${outcomeLine(ws.expected_outcome, "dim")}`);
|
|
30845
30907
|
for (const li of ws.leading_indicators) {
|
|
30846
|
-
|
|
30908
|
+
lines.push(`${INDENT} ${chalk24.dim("Lead:")} ${outcomeLine(li, "dim")}`);
|
|
30847
30909
|
}
|
|
30848
30910
|
if (ws.actions.length > 0) {
|
|
30849
|
-
|
|
30911
|
+
lines.push(`${INDENT} ${chalk24.dim("First steps")}`);
|
|
30850
30912
|
for (const action of ws.actions.slice(0, 3)) {
|
|
30851
|
-
|
|
30913
|
+
collectWrapped(lines, `- ${action}`, width - 7, INDENT + " ", (s) => chalk24.dim(s));
|
|
30852
30914
|
}
|
|
30853
30915
|
}
|
|
30854
30916
|
if (ws.milestones.length > 0) {
|
|
30855
|
-
|
|
30917
|
+
lines.push(`${INDENT} ${chalk24.dim("Milestones")}`);
|
|
30856
30918
|
for (const m of ws.milestones) {
|
|
30857
|
-
|
|
30919
|
+
lines.push(`${INDENT} ${paint("accent", m.due)} ${m.label}`);
|
|
30858
30920
|
}
|
|
30859
30921
|
}
|
|
30860
30922
|
if (ws.deliverables.length > 0) {
|
|
30861
|
-
|
|
30923
|
+
lines.push(`${INDENT} ${chalk24.dim("Deliverables")}`);
|
|
30862
30924
|
for (const d of ws.deliverables) {
|
|
30863
|
-
|
|
30925
|
+
lines.push(`${INDENT} ${chalk24.dim("[ ]")} ${d.label} ${chalk24.dim(`due ${d.due}`)}`);
|
|
30864
30926
|
}
|
|
30865
30927
|
}
|
|
30866
|
-
|
|
30928
|
+
collectWrapped(
|
|
30929
|
+
lines,
|
|
30867
30930
|
`If ${ws.contingency.trigger} (check ${ws.contingency.trigger_check_date}), then ${ws.contingency.fallback}`,
|
|
30868
30931
|
width - 5,
|
|
30869
30932
|
INDENT + " ",
|
|
30870
30933
|
(s) => chalk24.dim(s)
|
|
30871
30934
|
);
|
|
30872
|
-
|
|
30873
|
-
|
|
30935
|
+
lines.push(`${INDENT} ${chalk24.dim(`~${Math.round(ws.effort_hours)} team hours`)}`);
|
|
30936
|
+
lines.push("");
|
|
30937
|
+
return lines;
|
|
30874
30938
|
}
|
|
30875
|
-
function
|
|
30939
|
+
function renderOperatorList(title, items, width) {
|
|
30940
|
+
const lines = [];
|
|
30941
|
+
if (items.length === 0) return lines;
|
|
30942
|
+
lines.push(`${INDENT}${chalk24.dim(title)}`);
|
|
30943
|
+
for (const item of items) {
|
|
30944
|
+
collectWrapped(lines, `- ${item}`, width - 2, INDENT, (s) => chalk24.dim(s));
|
|
30945
|
+
}
|
|
30946
|
+
lines.push("");
|
|
30947
|
+
return lines;
|
|
30948
|
+
}
|
|
30949
|
+
function renderStrategyBrief(plan, stats, opts = {}) {
|
|
30950
|
+
const mode = opts.mode ?? "foh";
|
|
30876
30951
|
const width = Math.min(termWidth() - 4, 92);
|
|
30877
|
-
|
|
30878
|
-
|
|
30952
|
+
const lines = [""];
|
|
30953
|
+
lines.push(
|
|
30879
30954
|
`${INDENT}${chalk24.bold(`Strategy brief \u2014 ${plan.title}`)} ${chalk24.dim(`confidence ${plan.confidence.toFixed(2)} \xB7 ${plan.priority} priority \xB7 review ${plan.review_cadence.toLowerCase()}`)}`
|
|
30880
30955
|
);
|
|
30881
|
-
|
|
30882
|
-
|
|
30883
|
-
|
|
30884
|
-
|
|
30885
|
-
|
|
30886
|
-
|
|
30887
|
-
|
|
30888
|
-
printWorkstream(ws, width);
|
|
30889
|
-
}
|
|
30890
|
-
const constraints = filterOperatorLines(plan.constraints);
|
|
30891
|
-
if (constraints.length > 0) {
|
|
30892
|
-
console.log(`${INDENT}${chalk24.dim("Constraints")}`);
|
|
30893
|
-
for (const c of constraints) {
|
|
30894
|
-
printWrapped(`- ${c}`, width - 2, INDENT, (s) => chalk24.dim(s));
|
|
30956
|
+
if (mode === "foh") {
|
|
30957
|
+
collectWrapped(lines, altitudeLine(plan.summary_30k), width, INDENT);
|
|
30958
|
+
lines.push("");
|
|
30959
|
+
collectWrapped(lines, altitudeLine(plan.objective), width, INDENT, (s) => paint("accent", s));
|
|
30960
|
+
lines.push("");
|
|
30961
|
+
for (const ws of plan.workstreams) {
|
|
30962
|
+
lines.push(...renderFohWorkstream(ws, width));
|
|
30895
30963
|
}
|
|
30896
|
-
|
|
30897
|
-
|
|
30898
|
-
|
|
30899
|
-
|
|
30900
|
-
|
|
30901
|
-
|
|
30902
|
-
|
|
30964
|
+
} else {
|
|
30965
|
+
lines.push(INDENT + chalk24.dim(hr(width)));
|
|
30966
|
+
lines.push(`${INDENT}${chalk24.dim("The Call")}`);
|
|
30967
|
+
collectWrapped(lines, plan.summary_30k, width);
|
|
30968
|
+
lines.push("");
|
|
30969
|
+
collectWrapped(lines, `Objective: ${plan.objective}`, width, INDENT, (s) => paint("accent", s));
|
|
30970
|
+
lines.push("");
|
|
30971
|
+
for (const ws of plan.workstreams) {
|
|
30972
|
+
lines.push(...renderBohWorkstream(ws, width));
|
|
30903
30973
|
}
|
|
30904
|
-
|
|
30974
|
+
lines.push(
|
|
30975
|
+
...renderOperatorList("Constraints", filterOperatorLines(plan.constraints), width)
|
|
30976
|
+
);
|
|
30977
|
+
lines.push(
|
|
30978
|
+
...renderOperatorList(
|
|
30979
|
+
"Assumptions (not verified, not targets)",
|
|
30980
|
+
filterOperatorLines(plan.assumptions),
|
|
30981
|
+
width
|
|
30982
|
+
)
|
|
30983
|
+
);
|
|
30984
|
+
lines.push(...renderOperatorList("Risks", filterOperatorLines(plan.risks), width));
|
|
30905
30985
|
}
|
|
30906
|
-
|
|
30907
|
-
|
|
30908
|
-
|
|
30909
|
-
|
|
30910
|
-
printWrapped(`- ${r}`, width - 2, INDENT, (s) => chalk24.dim(s));
|
|
30911
|
-
}
|
|
30912
|
-
console.log();
|
|
30986
|
+
lines.push(INDENT + chalk24.dim(hr(width)));
|
|
30987
|
+
lines.push(`${INDENT}${coverageLine(plan, stats)}`);
|
|
30988
|
+
if (opts.hint) {
|
|
30989
|
+
lines.push(`${INDENT}${chalk24.dim(STRATEGY_BRIEF_EXPAND_HINT)}`);
|
|
30913
30990
|
}
|
|
30914
|
-
|
|
30915
|
-
|
|
30916
|
-
|
|
30917
|
-
|
|
30918
|
-
console.log(
|
|
30919
|
-
|
|
30991
|
+
lines.push("");
|
|
30992
|
+
return lines.join("\n");
|
|
30993
|
+
}
|
|
30994
|
+
function printStrategyBrief(plan, stats, opts = {}) {
|
|
30995
|
+
console.log(renderStrategyBrief(plan, stats, opts));
|
|
30996
|
+
}
|
|
30997
|
+
function resolveStrategyBriefMode(host) {
|
|
30998
|
+
return isVerbose(host.execution) ? "boh" : "foh";
|
|
30999
|
+
}
|
|
31000
|
+
function presentStrategyBrief(host, plan, stats, notices = [], meta = {}) {
|
|
31001
|
+
const mode = resolveStrategyBriefMode(host);
|
|
31002
|
+
printStrategyBrief(plan, stats, { mode, hint: mode === "foh" && !host.oneShot });
|
|
31003
|
+
printStrategyBriefFooter(notices, meta);
|
|
31004
|
+
host.lastStrategyBrief = { plan, stats, notices, meta };
|
|
31005
|
+
}
|
|
31006
|
+
function expandLastStrategyBrief(host) {
|
|
31007
|
+
const last = host.lastStrategyBrief;
|
|
31008
|
+
if (!last) return false;
|
|
31009
|
+
printStrategyBrief(last.plan, last.stats, { mode: "boh", hint: false });
|
|
31010
|
+
printStrategyBriefFooter(last.notices, last.meta);
|
|
31011
|
+
return true;
|
|
31012
|
+
}
|
|
31013
|
+
function isBriefExpandInput(input) {
|
|
31014
|
+
return /^(more|expand)\s*[.!]?\s*$/i.test(input.trim());
|
|
31015
|
+
}
|
|
31016
|
+
function planFromStrategy(strategy) {
|
|
31017
|
+
return {
|
|
31018
|
+
title: strategy.title,
|
|
31019
|
+
objective: strategy.objective || strategy.goal,
|
|
31020
|
+
summary_30k: strategy.raw_excerpt || strategy.goal,
|
|
31021
|
+
hypothesis: strategy.hypothesis,
|
|
31022
|
+
target_segment: strategy.target_segment,
|
|
31023
|
+
priority: strategy.priority,
|
|
31024
|
+
review_cadence: strategy.review_cadence,
|
|
31025
|
+
confidence: strategy.confidence,
|
|
31026
|
+
constraints: strategy.constraints,
|
|
31027
|
+
assumptions: strategy.assumptions,
|
|
31028
|
+
risks: strategy.risks,
|
|
31029
|
+
workstreams: strategy.workstreams
|
|
31030
|
+
};
|
|
31031
|
+
}
|
|
31032
|
+
function statsFromPlan(plan) {
|
|
31033
|
+
let total = 0;
|
|
31034
|
+
for (const ws of plan.workstreams) {
|
|
31035
|
+
total += 1;
|
|
31036
|
+
total += ws.leading_indicators.length;
|
|
31037
|
+
}
|
|
31038
|
+
return { measurable_targets: total, total_targets: total };
|
|
30920
31039
|
}
|
|
30921
31040
|
function printStrategyBriefFooter(notices, meta) {
|
|
30922
31041
|
if (usedGroundedFallback(notices)) {
|
|
@@ -30935,7 +31054,10 @@ function printCraftWrapUp(opts) {
|
|
|
30935
31054
|
);
|
|
30936
31055
|
}
|
|
30937
31056
|
const handoff = opts.inbox_path ?? opts.handoff_path;
|
|
30938
|
-
if (handoff)
|
|
31057
|
+
if (handoff) {
|
|
31058
|
+
console.log(INDENT + chalk24.dim(handoff));
|
|
31059
|
+
printExportPickupNudge({ inboxReady: Boolean(opts.inbox_path) });
|
|
31060
|
+
}
|
|
30939
31061
|
} else {
|
|
30940
31062
|
console.log(INDENT + paint("accent", "Best so far."));
|
|
30941
31063
|
const path = opts.library_path ?? opts.handoff_path ?? opts.inbox_path;
|
|
@@ -30955,15 +31077,20 @@ function printCraftWrapUp(opts) {
|
|
|
30955
31077
|
}
|
|
30956
31078
|
console.log();
|
|
30957
31079
|
}
|
|
30958
|
-
var INDENT;
|
|
31080
|
+
var STRATEGY_BRIEF_EXPAND_HINT, INDENT, FOH_PROSE_MAX;
|
|
30959
31081
|
var init_strategy_brief = __esm({
|
|
30960
31082
|
"src/output/strategy-brief.ts"() {
|
|
30961
31083
|
"use strict";
|
|
30962
31084
|
init_theme();
|
|
30963
31085
|
init_layout();
|
|
31086
|
+
init_formatters();
|
|
30964
31087
|
init_strategy_signal();
|
|
30965
31088
|
init_llm_attribution();
|
|
31089
|
+
init_handoff_skill();
|
|
31090
|
+
init_verbosity();
|
|
31091
|
+
STRATEGY_BRIEF_EXPAND_HINT = "Type more to show the full brief.";
|
|
30966
31092
|
INDENT = " ";
|
|
31093
|
+
FOH_PROSE_MAX = 220;
|
|
30967
31094
|
}
|
|
30968
31095
|
});
|
|
30969
31096
|
|
|
@@ -31324,8 +31451,7 @@ async function runStrategistSession(ctx) {
|
|
|
31324
31451
|
console.log();
|
|
31325
31452
|
return;
|
|
31326
31453
|
}
|
|
31327
|
-
|
|
31328
|
-
printStrategyBriefFooter(notices, meta);
|
|
31454
|
+
presentStrategyBrief(ctx, plan, stats, notices, meta);
|
|
31329
31455
|
console.log();
|
|
31330
31456
|
let saved = false;
|
|
31331
31457
|
if (ctx.rl) {
|
|
@@ -31384,14 +31510,14 @@ async function ensureSnapshot(ctx) {
|
|
|
31384
31510
|
}
|
|
31385
31511
|
function printCraftReplResult(ctx, result, objective) {
|
|
31386
31512
|
if (result.plan) {
|
|
31387
|
-
|
|
31513
|
+
presentStrategyBrief(ctx, result.plan, {
|
|
31388
31514
|
measurable_targets: result.measurable_targets,
|
|
31389
31515
|
total_targets: result.total_targets
|
|
31390
|
-
});
|
|
31516
|
+
}, result.notices, result.usage);
|
|
31391
31517
|
} else {
|
|
31392
31518
|
console.log(" " + chalk25.dim("(No plan produced)"));
|
|
31519
|
+
printStrategyBriefFooter(result.notices, result.usage);
|
|
31393
31520
|
}
|
|
31394
|
-
printStrategyBriefFooter(result.notices, result.usage);
|
|
31395
31521
|
if (result.library_path) creditStrategySession(ctx);
|
|
31396
31522
|
printCraftWrapUp({
|
|
31397
31523
|
status: result.status,
|
|
@@ -32001,7 +32127,7 @@ function matchDefinitionExplainer(input) {
|
|
|
32001
32127
|
}
|
|
32002
32128
|
return getMetricExplainer(id);
|
|
32003
32129
|
}
|
|
32004
|
-
function
|
|
32130
|
+
function printWrapped(text, indent = " ") {
|
|
32005
32131
|
for (const line of wrapWords(text, 78)) {
|
|
32006
32132
|
console.log(indent + line);
|
|
32007
32133
|
}
|
|
@@ -32018,10 +32144,10 @@ function tryKeylessDefinitionAnswer(ctx, input) {
|
|
|
32018
32144
|
console.log(" " + chalk29.dim(explainer.tagline));
|
|
32019
32145
|
console.log();
|
|
32020
32146
|
console.log(" " + bold("Meaning"));
|
|
32021
|
-
|
|
32147
|
+
printWrapped(explainer.meaning, " ");
|
|
32022
32148
|
console.log();
|
|
32023
32149
|
console.log(" " + bold("How NTRP calculates it"));
|
|
32024
|
-
|
|
32150
|
+
printWrapped(explainer.how_computed, " ");
|
|
32025
32151
|
for (const f of explainer.formula_lines) {
|
|
32026
32152
|
console.log(" " + paint("accent", f));
|
|
32027
32153
|
}
|
|
@@ -36708,6 +36834,7 @@ async function handler10(args, _ctx) {
|
|
|
36708
36834
|
if (event.inbox_path) {
|
|
36709
36835
|
console.log(chalk43.dim(` Inbox: ${event.inbox_path}`));
|
|
36710
36836
|
}
|
|
36837
|
+
printExportPickupNudge({ inboxReady: Boolean(event.inbox_path) });
|
|
36711
36838
|
console.log();
|
|
36712
36839
|
return filepath;
|
|
36713
36840
|
} catch (err) {
|
|
@@ -36724,6 +36851,7 @@ var init_export = __esm({
|
|
|
36724
36851
|
init_path_safety();
|
|
36725
36852
|
init_argparse();
|
|
36726
36853
|
init_exports_registry();
|
|
36854
|
+
init_handoff_skill();
|
|
36727
36855
|
init_segments();
|
|
36728
36856
|
}
|
|
36729
36857
|
});
|
|
@@ -36822,6 +36950,7 @@ async function handler11(args, _ctx) {
|
|
|
36822
36950
|
if (event.inbox_path) {
|
|
36823
36951
|
console.log(chalk44.dim(` Inbox: ${event.inbox_path}`));
|
|
36824
36952
|
}
|
|
36953
|
+
printExportPickupNudge({ inboxReady: Boolean(event.inbox_path) });
|
|
36825
36954
|
console.log();
|
|
36826
36955
|
return folder;
|
|
36827
36956
|
} catch (err) {
|
|
@@ -36839,6 +36968,7 @@ var init_backmeup = __esm({
|
|
|
36839
36968
|
init_formatters();
|
|
36840
36969
|
init_path_safety();
|
|
36841
36970
|
init_exports_registry();
|
|
36971
|
+
init_handoff_skill();
|
|
36842
36972
|
EVIDENCE_FILENAMES = {
|
|
36843
36973
|
freshness: "freshness.csv",
|
|
36844
36974
|
flow_rate: "flow-rate.csv",
|
|
@@ -38423,7 +38553,7 @@ async function handler16(args, ctx) {
|
|
|
38423
38553
|
emitResult("strategy", result);
|
|
38424
38554
|
return;
|
|
38425
38555
|
}
|
|
38426
|
-
renderStrategyResult(result);
|
|
38556
|
+
renderStrategyResult(result, ctx);
|
|
38427
38557
|
} catch (err) {
|
|
38428
38558
|
if (isStructuredOutput(ctx.execution)) emitError(first === "craft" ? "strategy.craft" : "strategy", err);
|
|
38429
38559
|
console.error(chalk50.red(` ${err instanceof Error ? err.message : String(err)}`));
|
|
@@ -38579,10 +38709,10 @@ function craftJsonData(result) {
|
|
|
38579
38709
|
stop_reason: result.stop_reason ?? null
|
|
38580
38710
|
};
|
|
38581
38711
|
}
|
|
38582
|
-
function renderStrategyResult(result) {
|
|
38712
|
+
function renderStrategyResult(result, ctx) {
|
|
38583
38713
|
switch (result.action) {
|
|
38584
38714
|
case "craft":
|
|
38585
|
-
renderCraftResult(result);
|
|
38715
|
+
renderCraftResult(result, ctx);
|
|
38586
38716
|
return;
|
|
38587
38717
|
case "review":
|
|
38588
38718
|
return;
|
|
@@ -38598,8 +38728,7 @@ function renderStrategyResult(result) {
|
|
|
38598
38728
|
printStrategyList(result.strategies);
|
|
38599
38729
|
return;
|
|
38600
38730
|
case "show":
|
|
38601
|
-
|
|
38602
|
-
printStrategyDetail(result.strategy);
|
|
38731
|
+
printStrategyShow(result.strategy, ctx);
|
|
38603
38732
|
if (result.sources.length > 0) {
|
|
38604
38733
|
console.log(chalk50.hex("#14b8a6")(" Sources"));
|
|
38605
38734
|
for (const source of result.sources) {
|
|
@@ -38616,17 +38745,17 @@ function renderStrategyResult(result) {
|
|
|
38616
38745
|
return;
|
|
38617
38746
|
}
|
|
38618
38747
|
}
|
|
38619
|
-
function renderCraftResult(result) {
|
|
38748
|
+
function renderCraftResult(result, ctx) {
|
|
38620
38749
|
if (result.plan) {
|
|
38621
|
-
|
|
38750
|
+
presentStrategyBrief(ctx, result.plan, {
|
|
38622
38751
|
measurable_targets: result.measurable_targets,
|
|
38623
38752
|
total_targets: result.total_targets
|
|
38624
|
-
});
|
|
38753
|
+
}, result.notices, result.usage);
|
|
38625
38754
|
} else {
|
|
38626
38755
|
console.log();
|
|
38627
38756
|
console.log(" " + chalk50.dim("(No plan produced)"));
|
|
38757
|
+
printStrategyBriefFooter(result.notices, result.usage);
|
|
38628
38758
|
}
|
|
38629
|
-
printStrategyBriefFooter(result.notices, result.usage);
|
|
38630
38759
|
printCraftWrapUp({
|
|
38631
38760
|
status: result.status,
|
|
38632
38761
|
library_path: result.library_path,
|
|
@@ -38657,29 +38786,21 @@ function printStrategySummary(strategy) {
|
|
|
38657
38786
|
console.log(` ${strategy.goal}`);
|
|
38658
38787
|
console.log();
|
|
38659
38788
|
}
|
|
38660
|
-
function
|
|
38661
|
-
|
|
38662
|
-
|
|
38663
|
-
|
|
38664
|
-
|
|
38665
|
-
|
|
38666
|
-
|
|
38667
|
-
console.log();
|
|
38668
|
-
if (strategy.linked_play_ids.length > 0) {
|
|
38669
|
-
console.log(chalk50.hex("#14b8a6")(" Linked Plays"));
|
|
38670
|
-
console.log(` ${strategy.linked_play_ids.join(", ")}`);
|
|
38671
|
-
console.log();
|
|
38672
|
-
}
|
|
38673
|
-
if (strategy.success_metrics.length > 0) {
|
|
38674
|
-
console.log(chalk50.hex("#14b8a6")(" Success Metrics"));
|
|
38675
|
-
for (const metric of strategy.success_metrics) {
|
|
38676
|
-
console.log(` - ${metric.name}${metric.target ? `: ${metric.target}` : ""}`);
|
|
38789
|
+
function printStrategyShow(strategy, ctx) {
|
|
38790
|
+
if (strategy.workstreams.length > 0) {
|
|
38791
|
+
const plan = planFromStrategy(strategy);
|
|
38792
|
+
presentStrategyBrief(ctx, plan, statsFromPlan(plan));
|
|
38793
|
+
if (strategy.library_path) {
|
|
38794
|
+
console.log(" " + chalk50.dim(strategy.library_path));
|
|
38795
|
+
console.log();
|
|
38677
38796
|
}
|
|
38797
|
+
return;
|
|
38798
|
+
}
|
|
38799
|
+
printStrategySummary(strategy);
|
|
38800
|
+
if (strategy.library_path) {
|
|
38801
|
+
console.log(" " + chalk50.dim(strategy.library_path));
|
|
38678
38802
|
console.log();
|
|
38679
38803
|
}
|
|
38680
|
-
console.log(chalk50.hex("#14b8a6")(" Experiment Design"));
|
|
38681
|
-
console.log(` ${strategy.experiment_design}`);
|
|
38682
|
-
console.log();
|
|
38683
38804
|
}
|
|
38684
38805
|
function statusBadge3(status) {
|
|
38685
38806
|
switch (status) {
|
|
@@ -45961,6 +46082,18 @@ function handleBackNavigation(ctx, line) {
|
|
|
45961
46082
|
}
|
|
45962
46083
|
return null;
|
|
45963
46084
|
}
|
|
46085
|
+
function handleBriefExpand(ctx, line) {
|
|
46086
|
+
if (!isBriefExpandInput(line)) return null;
|
|
46087
|
+
if (!ctx.lastStrategyBrief) return null;
|
|
46088
|
+
const phase = resolveConversationPhase(ctx);
|
|
46089
|
+
if (phase === "scope" || phase === "awaiting_data" || phase === "strategize" || phase === "think" || phase === "deliver") {
|
|
46090
|
+
return null;
|
|
46091
|
+
}
|
|
46092
|
+
recordMessage(ctx, "user", line);
|
|
46093
|
+
expandLastStrategyBrief(ctx);
|
|
46094
|
+
recordMessage(ctx, "agent", "Full strategy brief");
|
|
46095
|
+
return { handled: true, summary: "Full strategy brief" };
|
|
46096
|
+
}
|
|
45964
46097
|
async function conversationRouter(input, ctx) {
|
|
45965
46098
|
if (ctx.oneShot || (ctx.wizardDepth ?? 0) > 0) {
|
|
45966
46099
|
return { handled: false };
|
|
@@ -46020,6 +46153,8 @@ async function conversationRouter(input, ctx) {
|
|
|
46020
46153
|
}
|
|
46021
46154
|
const backResult = handleBackNavigation(ctx, line);
|
|
46022
46155
|
if (backResult) return backResult;
|
|
46156
|
+
const expandResult = handleBriefExpand(ctx, line);
|
|
46157
|
+
if (expandResult) return expandResult;
|
|
46023
46158
|
if (/^\S+$/.test(line) && !/^\d$/.test(line)) {
|
|
46024
46159
|
const { resolveSessionByToken: resolveSessionByToken2 } = await Promise.resolve().then(() => (init_context2(), context_exports));
|
|
46025
46160
|
if (resolveSessionByToken2(line, { printErrors: false }) !== void 0) {
|
|
@@ -46131,6 +46266,7 @@ var init_router = __esm({
|
|
|
46131
46266
|
init_demo();
|
|
46132
46267
|
init_scope();
|
|
46133
46268
|
init_pending_ask();
|
|
46269
|
+
init_strategy_brief();
|
|
46134
46270
|
FRESH_START_RE = /\b(start (over|fresh)|new analysis|start again|reset session)\b/i;
|
|
46135
46271
|
CANCEL_ESCAPE_RE = /^(cancel|stop|abort|quit|never\s?mind|nevermind|forget it)\s*[.!]?\s*$/i;
|
|
46136
46272
|
}
|
|
@@ -47235,6 +47371,9 @@ function printHelp() {
|
|
|
47235
47371
|
console.log(
|
|
47236
47372
|
" " + chalk96.dim("On ") + paint("accent", "/settings") + chalk96.dim(" menus, ") + paint("accent", "b") + chalk96.dim(" leaves the hub (same as Done).")
|
|
47237
47373
|
);
|
|
47374
|
+
console.log(
|
|
47375
|
+
" " + paint("accent", "more") + chalk96.dim(" / ") + paint("accent", "expand") + chalk96.dim(" Shows the full strategy brief after the short summary.")
|
|
47376
|
+
);
|
|
47238
47377
|
console.log(
|
|
47239
47378
|
" " + paint("accent", "cancel") + chalk96.dim(" Drops the current modal overlay (strategy, think, ship, unconfirmed scope).")
|
|
47240
47379
|
);
|
package/dist/mcp/server.js
CHANGED
|
@@ -1308,6 +1308,34 @@ function voiceHealthGloss(status, prefs) {
|
|
|
1308
1308
|
}
|
|
1309
1309
|
});
|
|
1310
1310
|
}
|
|
1311
|
+
function voiceExportPickupNudge(input, prefs) {
|
|
1312
|
+
const v = voice(prefs);
|
|
1313
|
+
const phrase = EXPORT_PICKUP_PHRASE;
|
|
1314
|
+
if (input.inboxReady) {
|
|
1315
|
+
return pick(v, {
|
|
1316
|
+
robotic: `Open your desktop AI. Tell it to ${phrase}.`,
|
|
1317
|
+
composed: `Open your desktop AI and tell it to ${phrase}.`,
|
|
1318
|
+
casual: `This terminal is not your AI. Open it and tell it to ${phrase}.`,
|
|
1319
|
+
loose: {
|
|
1320
|
+
light: `Written. Open your desktop AI and tell it to ${phrase}.`,
|
|
1321
|
+
medium: `This CLI cannot see your AI. Open it. Tell it to ${phrase}.`,
|
|
1322
|
+
dark: `The file is on disk. Your AI is not in this window. Open it and ${phrase}.`,
|
|
1323
|
+
heavy: `NTRP wrote it. This window is not your AI. Open the desktop app and ${phrase}.`
|
|
1324
|
+
}
|
|
1325
|
+
});
|
|
1326
|
+
}
|
|
1327
|
+
return pick(v, {
|
|
1328
|
+
robotic: `Your desktop AI cannot see this folder. Type /inbox set, then tell that AI to ${phrase}.`,
|
|
1329
|
+
composed: `These files are on disk. Set a pickup folder (/inbox set), then tell your desktop AI to ${phrase}.`,
|
|
1330
|
+
casual: `Your AI cannot see this folder. Type /inbox set, then tell it to ${phrase}.`,
|
|
1331
|
+
loose: {
|
|
1332
|
+
light: `Your AI cannot see this folder yet. Type /inbox set, then tell it to ${phrase}.`,
|
|
1333
|
+
medium: `This folder is invisible to your AI. Type /inbox set, then tell it to ${phrase}.`,
|
|
1334
|
+
dark: `Your AI cannot see this terminal. Type /inbox set, then ${phrase}.`,
|
|
1335
|
+
heavy: `This window is not your AI. Type /inbox set, then ${phrase}.`
|
|
1336
|
+
}
|
|
1337
|
+
});
|
|
1338
|
+
}
|
|
1311
1339
|
function voiceHandoffAddendum(prefs) {
|
|
1312
1340
|
const v = voice(prefs);
|
|
1313
1341
|
return [
|
|
@@ -1322,11 +1350,13 @@ function pick(prefs, map) {
|
|
|
1322
1350
|
if (typeof entry === "string") return entry;
|
|
1323
1351
|
return entry[prefs.roast];
|
|
1324
1352
|
}
|
|
1353
|
+
var EXPORT_PICKUP_PHRASE;
|
|
1325
1354
|
var init_copy = __esm({
|
|
1326
1355
|
"src/voice/copy.ts"() {
|
|
1327
1356
|
"use strict";
|
|
1328
1357
|
init_catalog();
|
|
1329
1358
|
init_prefs();
|
|
1359
|
+
EXPORT_PICKUP_PHRASE = "pick up the latest NTRP handoff";
|
|
1330
1360
|
}
|
|
1331
1361
|
});
|
|
1332
1362
|
|
|
@@ -2533,6 +2563,9 @@ function maybePrintAiInboxNudge() {
|
|
|
2533
2563
|
)
|
|
2534
2564
|
);
|
|
2535
2565
|
}
|
|
2566
|
+
function printExportPickupNudge(opts) {
|
|
2567
|
+
console.log(" " + chalk7.dim(voiceExportPickupNudge(opts)));
|
|
2568
|
+
}
|
|
2536
2569
|
function printStandingSkill() {
|
|
2537
2570
|
persistStandingSkill();
|
|
2538
2571
|
const loc = handoffLocations();
|
|
@@ -2558,6 +2591,7 @@ var init_handoff_skill = __esm({
|
|
|
2558
2591
|
init_store();
|
|
2559
2592
|
init_theme();
|
|
2560
2593
|
init_export_kinds();
|
|
2594
|
+
init_copy();
|
|
2561
2595
|
STANDING_SKILL_NAME = "SKILL.md";
|
|
2562
2596
|
ARCHIVE_PICKUP_NAME = "pickup.md";
|
|
2563
2597
|
INBOX_PICKUP_NAME = "latest-pickup.md";
|
|
@@ -9680,7 +9714,7 @@ ${strategy.objective}
|
|
|
9680
9714
|
` : "";
|
|
9681
9715
|
const workstreamSection = strategy.workstreams.length > 0 ? `
|
|
9682
9716
|
## Workstreams
|
|
9683
|
-
${strategy.workstreams.map(
|
|
9717
|
+
${strategy.workstreams.map(formatWorkstreamMarkdown).join("\n")}
|
|
9684
9718
|
` : "";
|
|
9685
9719
|
const constraintsSection = filterOperatorLines(strategy.constraints).length > 0 ? `
|
|
9686
9720
|
## Constraints
|
|
@@ -9736,7 +9770,7 @@ ${strategy.objective}
|
|
|
9736
9770
|
` : "";
|
|
9737
9771
|
const workstreamSection = strategy.workstreams.length > 0 ? `
|
|
9738
9772
|
## Workstreams
|
|
9739
|
-
${strategy.workstreams.map(
|
|
9773
|
+
${strategy.workstreams.map(formatWorkstreamMarkdown).join("\n")}
|
|
9740
9774
|
` : "";
|
|
9741
9775
|
const assumptions = filterOperatorLines(strategy.assumptions);
|
|
9742
9776
|
const assumptionsSection = assumptions.length > 0 ? `
|
|
@@ -9783,7 +9817,7 @@ ${frontmatter}
|
|
|
9783
9817
|
].filter((p) => p != null && String(p).length > 0);
|
|
9784
9818
|
return parts.join("\n\n") + "\n";
|
|
9785
9819
|
}
|
|
9786
|
-
function
|
|
9820
|
+
function formatWorkstreamMarkdown(ws) {
|
|
9787
9821
|
const lines = [];
|
|
9788
9822
|
lines.push(`### ${ws.order}. ${ws.title}`);
|
|
9789
9823
|
lines.push(`- Problem: ${ws.problem}`);
|
|
@@ -11146,6 +11180,7 @@ function resetContextForSwitch(ctx, opts) {
|
|
|
11146
11180
|
ctx.thinkState = opts.thinkState;
|
|
11147
11181
|
ctx.pendingAsk = opts.pendingAsk;
|
|
11148
11182
|
ctx.lastCraftJobId = opts.lastCraftJobId;
|
|
11183
|
+
ctx.lastStrategyBrief = void 0;
|
|
11149
11184
|
ctx.gapAudit = void 0;
|
|
11150
11185
|
ctx.deliverIntent = false;
|
|
11151
11186
|
ctx.computeInProgress = false;
|
|
@@ -23835,20 +23870,7 @@ function renderCraftHandoffMarkdown(opts) {
|
|
|
23835
23870
|
lines.push("## Workstreams");
|
|
23836
23871
|
lines.push("");
|
|
23837
23872
|
for (const ws of plan.workstreams) {
|
|
23838
|
-
lines.push(
|
|
23839
|
-
lines.push("");
|
|
23840
|
-
lines.push(`- Problem: ${ws.problem}`);
|
|
23841
|
-
if (ws.rationale && !isGenericWorkstreamRationale(ws.rationale)) {
|
|
23842
|
-
lines.push(`- Why this order: ${ws.rationale}`);
|
|
23843
|
-
}
|
|
23844
|
-
if (ws.actions[0]) lines.push(`- First action (48h): ${ws.actions[0]}`);
|
|
23845
|
-
lines.push(`- Effort: ~${Math.round(ws.effort_hours)} team-hours`);
|
|
23846
|
-
lines.push(
|
|
23847
|
-
`- Exam: ${ws.expected_outcome.metric} ${ws.expected_outcome.baseline} \u2192 ${ws.expected_outcome.target_range} by ${ws.expected_outcome.check_date} (${ws.expected_outcome.measured_by})`
|
|
23848
|
-
);
|
|
23849
|
-
lines.push(
|
|
23850
|
-
`- Contingency: if ${ws.contingency.trigger} (check ${ws.contingency.trigger_check_date}) \u2192 ${ws.contingency.fallback}`
|
|
23851
|
-
);
|
|
23873
|
+
lines.push(formatWorkstreamMarkdown(ws).trimEnd());
|
|
23852
23874
|
lines.push("");
|
|
23853
23875
|
}
|
|
23854
23876
|
if (opts.roundtableDigest) {
|
|
@@ -24128,93 +24150,149 @@ var init_llm_attribution = __esm({
|
|
|
24128
24150
|
|
|
24129
24151
|
// src/output/strategy-brief.ts
|
|
24130
24152
|
import chalk17 from "chalk";
|
|
24131
|
-
function
|
|
24153
|
+
function collectWrapped(lines, text, width, prefix = INDENT, style) {
|
|
24132
24154
|
for (const line of wrapWords(text, width)) {
|
|
24133
|
-
|
|
24155
|
+
lines.push(prefix + (style ? style(line) : line));
|
|
24134
24156
|
}
|
|
24135
24157
|
}
|
|
24136
|
-
function outcomeLine(outcome) {
|
|
24137
|
-
|
|
24158
|
+
function outcomeLine(outcome, dateStyle) {
|
|
24159
|
+
const by = dateStyle === "accent" ? paint("accent", `by ${outcome.check_date}`) : chalk17.dim(`by ${outcome.check_date}`);
|
|
24160
|
+
return `${chalk17.bold(outcome.metric)}: ${outcome.baseline} ${chalk17.dim("\u2192")} ${chalk17.bold(outcome.target_range)} ${by}`;
|
|
24161
|
+
}
|
|
24162
|
+
function soonestByDue(items) {
|
|
24163
|
+
if (items.length === 0) return void 0;
|
|
24164
|
+
return [...items].sort((a, b) => a.due.localeCompare(b.due) || 0)[0];
|
|
24138
24165
|
}
|
|
24139
|
-
function
|
|
24140
|
-
|
|
24141
|
-
|
|
24142
|
-
|
|
24166
|
+
function altitudeLine(text) {
|
|
24167
|
+
const sentence = findingHeadline(text) || text.trim();
|
|
24168
|
+
return truncateVisible(sentence, FOH_PROSE_MAX);
|
|
24169
|
+
}
|
|
24170
|
+
function coverageLine(plan, stats) {
|
|
24171
|
+
const totalHours = plan.workstreams.reduce((sum, ws) => sum + ws.effort_hours, 0);
|
|
24172
|
+
const hours = `~${Math.round(totalHours)} total team hours across ${plan.workstreams.length} workstream${plan.workstreams.length === 1 ? "" : "s"}`;
|
|
24173
|
+
if (stats.total_targets <= 0) return chalk17.dim(hours);
|
|
24174
|
+
const coverage = `${stats.measurable_targets} of ${stats.total_targets} targets can be measured with current data`;
|
|
24175
|
+
const coverageStyled = stats.measurable_targets === stats.total_targets ? paint("success", coverage) : chalk17.hex("#eab308")(coverage);
|
|
24176
|
+
return `${coverageStyled}${chalk17.dim(` \xB7 ${hours}`)}`;
|
|
24177
|
+
}
|
|
24178
|
+
function renderFohWorkstream(ws, width) {
|
|
24179
|
+
const lines = [];
|
|
24180
|
+
lines.push(`${INDENT}${paint("accent", `${ws.order}.`)} ${chalk17.bold(ws.title)}`);
|
|
24181
|
+
lines.push(`${INDENT} ${outcomeLine(ws.expected_outcome, "accent")}`);
|
|
24182
|
+
const next = soonestByDue(ws.milestones);
|
|
24183
|
+
if (next) {
|
|
24184
|
+
lines.push(`${INDENT} Next ${paint("accent", next.due)} ${next.label}`);
|
|
24185
|
+
}
|
|
24186
|
+
const ship = soonestByDue(ws.deliverables);
|
|
24187
|
+
if (ship) {
|
|
24188
|
+
lines.push(`${INDENT} Ship ${paint("accent", ship.due)} ${ship.label}`);
|
|
24189
|
+
}
|
|
24190
|
+
lines.push("");
|
|
24191
|
+
return lines;
|
|
24192
|
+
}
|
|
24193
|
+
function renderBohWorkstream(ws, width) {
|
|
24194
|
+
const lines = [];
|
|
24195
|
+
lines.push(`${INDENT}${paint("accent", `${ws.order}.`)} ${chalk17.bold(ws.title)}`);
|
|
24196
|
+
collectWrapped(lines, ws.problem, width - 5, INDENT + " ", (s) => chalk17.dim(s));
|
|
24197
|
+
lines.push(`${INDENT} ${outcomeLine(ws.expected_outcome, "dim")}`);
|
|
24143
24198
|
for (const li of ws.leading_indicators) {
|
|
24144
|
-
|
|
24199
|
+
lines.push(`${INDENT} ${chalk17.dim("Lead:")} ${outcomeLine(li, "dim")}`);
|
|
24145
24200
|
}
|
|
24146
24201
|
if (ws.actions.length > 0) {
|
|
24147
|
-
|
|
24202
|
+
lines.push(`${INDENT} ${chalk17.dim("First steps")}`);
|
|
24148
24203
|
for (const action of ws.actions.slice(0, 3)) {
|
|
24149
|
-
|
|
24204
|
+
collectWrapped(lines, `- ${action}`, width - 7, INDENT + " ", (s) => chalk17.dim(s));
|
|
24150
24205
|
}
|
|
24151
24206
|
}
|
|
24152
24207
|
if (ws.milestones.length > 0) {
|
|
24153
|
-
|
|
24208
|
+
lines.push(`${INDENT} ${chalk17.dim("Milestones")}`);
|
|
24154
24209
|
for (const m of ws.milestones) {
|
|
24155
|
-
|
|
24210
|
+
lines.push(`${INDENT} ${paint("accent", m.due)} ${m.label}`);
|
|
24156
24211
|
}
|
|
24157
24212
|
}
|
|
24158
24213
|
if (ws.deliverables.length > 0) {
|
|
24159
|
-
|
|
24214
|
+
lines.push(`${INDENT} ${chalk17.dim("Deliverables")}`);
|
|
24160
24215
|
for (const d of ws.deliverables) {
|
|
24161
|
-
|
|
24216
|
+
lines.push(`${INDENT} ${chalk17.dim("[ ]")} ${d.label} ${chalk17.dim(`due ${d.due}`)}`);
|
|
24162
24217
|
}
|
|
24163
24218
|
}
|
|
24164
|
-
|
|
24219
|
+
collectWrapped(
|
|
24220
|
+
lines,
|
|
24165
24221
|
`If ${ws.contingency.trigger} (check ${ws.contingency.trigger_check_date}), then ${ws.contingency.fallback}`,
|
|
24166
24222
|
width - 5,
|
|
24167
24223
|
INDENT + " ",
|
|
24168
24224
|
(s) => chalk17.dim(s)
|
|
24169
24225
|
);
|
|
24170
|
-
|
|
24171
|
-
|
|
24226
|
+
lines.push(`${INDENT} ${chalk17.dim(`~${Math.round(ws.effort_hours)} team hours`)}`);
|
|
24227
|
+
lines.push("");
|
|
24228
|
+
return lines;
|
|
24229
|
+
}
|
|
24230
|
+
function renderOperatorList(title, items, width) {
|
|
24231
|
+
const lines = [];
|
|
24232
|
+
if (items.length === 0) return lines;
|
|
24233
|
+
lines.push(`${INDENT}${chalk17.dim(title)}`);
|
|
24234
|
+
for (const item of items) {
|
|
24235
|
+
collectWrapped(lines, `- ${item}`, width - 2, INDENT, (s) => chalk17.dim(s));
|
|
24236
|
+
}
|
|
24237
|
+
lines.push("");
|
|
24238
|
+
return lines;
|
|
24172
24239
|
}
|
|
24173
|
-
function
|
|
24240
|
+
function renderStrategyBrief(plan, stats, opts = {}) {
|
|
24241
|
+
const mode = opts.mode ?? "foh";
|
|
24174
24242
|
const width = Math.min(termWidth() - 4, 92);
|
|
24175
|
-
|
|
24176
|
-
|
|
24243
|
+
const lines = [""];
|
|
24244
|
+
lines.push(
|
|
24177
24245
|
`${INDENT}${chalk17.bold(`Strategy brief \u2014 ${plan.title}`)} ${chalk17.dim(`confidence ${plan.confidence.toFixed(2)} \xB7 ${plan.priority} priority \xB7 review ${plan.review_cadence.toLowerCase()}`)}`
|
|
24178
24246
|
);
|
|
24179
|
-
|
|
24180
|
-
|
|
24181
|
-
|
|
24182
|
-
|
|
24183
|
-
|
|
24184
|
-
|
|
24185
|
-
|
|
24186
|
-
printWorkstream(ws, width);
|
|
24187
|
-
}
|
|
24188
|
-
const constraints = filterOperatorLines(plan.constraints);
|
|
24189
|
-
if (constraints.length > 0) {
|
|
24190
|
-
console.log(`${INDENT}${chalk17.dim("Constraints")}`);
|
|
24191
|
-
for (const c of constraints) {
|
|
24192
|
-
printWrapped(`- ${c}`, width - 2, INDENT, (s) => chalk17.dim(s));
|
|
24247
|
+
if (mode === "foh") {
|
|
24248
|
+
collectWrapped(lines, altitudeLine(plan.summary_30k), width, INDENT);
|
|
24249
|
+
lines.push("");
|
|
24250
|
+
collectWrapped(lines, altitudeLine(plan.objective), width, INDENT, (s) => paint("accent", s));
|
|
24251
|
+
lines.push("");
|
|
24252
|
+
for (const ws of plan.workstreams) {
|
|
24253
|
+
lines.push(...renderFohWorkstream(ws, width));
|
|
24193
24254
|
}
|
|
24194
|
-
|
|
24195
|
-
|
|
24196
|
-
|
|
24197
|
-
|
|
24198
|
-
|
|
24199
|
-
|
|
24200
|
-
|
|
24255
|
+
} else {
|
|
24256
|
+
lines.push(INDENT + chalk17.dim(hr(width)));
|
|
24257
|
+
lines.push(`${INDENT}${chalk17.dim("The Call")}`);
|
|
24258
|
+
collectWrapped(lines, plan.summary_30k, width);
|
|
24259
|
+
lines.push("");
|
|
24260
|
+
collectWrapped(lines, `Objective: ${plan.objective}`, width, INDENT, (s) => paint("accent", s));
|
|
24261
|
+
lines.push("");
|
|
24262
|
+
for (const ws of plan.workstreams) {
|
|
24263
|
+
lines.push(...renderBohWorkstream(ws, width));
|
|
24201
24264
|
}
|
|
24202
|
-
|
|
24265
|
+
lines.push(
|
|
24266
|
+
...renderOperatorList("Constraints", filterOperatorLines(plan.constraints), width)
|
|
24267
|
+
);
|
|
24268
|
+
lines.push(
|
|
24269
|
+
...renderOperatorList(
|
|
24270
|
+
"Assumptions (not verified, not targets)",
|
|
24271
|
+
filterOperatorLines(plan.assumptions),
|
|
24272
|
+
width
|
|
24273
|
+
)
|
|
24274
|
+
);
|
|
24275
|
+
lines.push(...renderOperatorList("Risks", filterOperatorLines(plan.risks), width));
|
|
24203
24276
|
}
|
|
24204
|
-
|
|
24205
|
-
|
|
24206
|
-
|
|
24207
|
-
|
|
24208
|
-
printWrapped(`- ${r}`, width - 2, INDENT, (s) => chalk17.dim(s));
|
|
24209
|
-
}
|
|
24210
|
-
console.log();
|
|
24277
|
+
lines.push(INDENT + chalk17.dim(hr(width)));
|
|
24278
|
+
lines.push(`${INDENT}${coverageLine(plan, stats)}`);
|
|
24279
|
+
if (opts.hint) {
|
|
24280
|
+
lines.push(`${INDENT}${chalk17.dim(STRATEGY_BRIEF_EXPAND_HINT)}`);
|
|
24211
24281
|
}
|
|
24212
|
-
|
|
24213
|
-
|
|
24214
|
-
|
|
24215
|
-
|
|
24216
|
-
console.log(
|
|
24217
|
-
|
|
24282
|
+
lines.push("");
|
|
24283
|
+
return lines.join("\n");
|
|
24284
|
+
}
|
|
24285
|
+
function printStrategyBrief(plan, stats, opts = {}) {
|
|
24286
|
+
console.log(renderStrategyBrief(plan, stats, opts));
|
|
24287
|
+
}
|
|
24288
|
+
function resolveStrategyBriefMode(host) {
|
|
24289
|
+
return isVerbose(host.execution) ? "boh" : "foh";
|
|
24290
|
+
}
|
|
24291
|
+
function presentStrategyBrief(host, plan, stats, notices = [], meta = {}) {
|
|
24292
|
+
const mode = resolveStrategyBriefMode(host);
|
|
24293
|
+
printStrategyBrief(plan, stats, { mode, hint: mode === "foh" && !host.oneShot });
|
|
24294
|
+
printStrategyBriefFooter(notices, meta);
|
|
24295
|
+
host.lastStrategyBrief = { plan, stats, notices, meta };
|
|
24218
24296
|
}
|
|
24219
24297
|
function printStrategyBriefFooter(notices, meta) {
|
|
24220
24298
|
if (usedGroundedFallback(notices)) {
|
|
@@ -24233,7 +24311,10 @@ function printCraftWrapUp(opts) {
|
|
|
24233
24311
|
);
|
|
24234
24312
|
}
|
|
24235
24313
|
const handoff = opts.inbox_path ?? opts.handoff_path;
|
|
24236
|
-
if (handoff)
|
|
24314
|
+
if (handoff) {
|
|
24315
|
+
console.log(INDENT + chalk17.dim(handoff));
|
|
24316
|
+
printExportPickupNudge({ inboxReady: Boolean(opts.inbox_path) });
|
|
24317
|
+
}
|
|
24237
24318
|
} else {
|
|
24238
24319
|
console.log(INDENT + paint("accent", "Best so far."));
|
|
24239
24320
|
const path = opts.library_path ?? opts.handoff_path ?? opts.inbox_path;
|
|
@@ -24253,15 +24334,20 @@ function printCraftWrapUp(opts) {
|
|
|
24253
24334
|
}
|
|
24254
24335
|
console.log();
|
|
24255
24336
|
}
|
|
24256
|
-
var INDENT;
|
|
24337
|
+
var STRATEGY_BRIEF_EXPAND_HINT, INDENT, FOH_PROSE_MAX;
|
|
24257
24338
|
var init_strategy_brief = __esm({
|
|
24258
24339
|
"src/output/strategy-brief.ts"() {
|
|
24259
24340
|
"use strict";
|
|
24260
24341
|
init_theme();
|
|
24261
24342
|
init_layout();
|
|
24343
|
+
init_formatters();
|
|
24262
24344
|
init_strategy_signal();
|
|
24263
24345
|
init_llm_attribution();
|
|
24346
|
+
init_handoff_skill();
|
|
24347
|
+
init_verbosity();
|
|
24348
|
+
STRATEGY_BRIEF_EXPAND_HINT = "Type more to show the full brief.";
|
|
24264
24349
|
INDENT = " ";
|
|
24350
|
+
FOH_PROSE_MAX = 220;
|
|
24265
24351
|
}
|
|
24266
24352
|
});
|
|
24267
24353
|
|
|
@@ -24622,8 +24708,7 @@ async function runStrategistSession(ctx) {
|
|
|
24622
24708
|
console.log();
|
|
24623
24709
|
return;
|
|
24624
24710
|
}
|
|
24625
|
-
|
|
24626
|
-
printStrategyBriefFooter(notices, meta);
|
|
24711
|
+
presentStrategyBrief(ctx, plan, stats, notices, meta);
|
|
24627
24712
|
console.log();
|
|
24628
24713
|
let saved = false;
|
|
24629
24714
|
if (ctx.rl) {
|
|
@@ -24682,14 +24767,14 @@ async function ensureSnapshot(ctx) {
|
|
|
24682
24767
|
}
|
|
24683
24768
|
function printCraftReplResult(ctx, result, objective) {
|
|
24684
24769
|
if (result.plan) {
|
|
24685
|
-
|
|
24770
|
+
presentStrategyBrief(ctx, result.plan, {
|
|
24686
24771
|
measurable_targets: result.measurable_targets,
|
|
24687
24772
|
total_targets: result.total_targets
|
|
24688
|
-
});
|
|
24773
|
+
}, result.notices, result.usage);
|
|
24689
24774
|
} else {
|
|
24690
24775
|
console.log(" " + chalk18.dim("(No plan produced)"));
|
|
24776
|
+
printStrategyBriefFooter(result.notices, result.usage);
|
|
24691
24777
|
}
|
|
24692
|
-
printStrategyBriefFooter(result.notices, result.usage);
|
|
24693
24778
|
if (result.library_path) creditStrategySession(ctx);
|
|
24694
24779
|
printCraftWrapUp({
|
|
24695
24780
|
status: result.status,
|
|
@@ -25542,7 +25627,7 @@ function matchDefinitionExplainer(input) {
|
|
|
25542
25627
|
}
|
|
25543
25628
|
return getMetricExplainer(id);
|
|
25544
25629
|
}
|
|
25545
|
-
function
|
|
25630
|
+
function printWrapped(text, indent = " ") {
|
|
25546
25631
|
for (const line of wrapWords(text, 78)) {
|
|
25547
25632
|
console.log(indent + line);
|
|
25548
25633
|
}
|
|
@@ -25559,10 +25644,10 @@ function tryKeylessDefinitionAnswer(ctx, input) {
|
|
|
25559
25644
|
console.log(" " + chalk23.dim(explainer.tagline));
|
|
25560
25645
|
console.log();
|
|
25561
25646
|
console.log(" " + bold("Meaning"));
|
|
25562
|
-
|
|
25647
|
+
printWrapped(explainer.meaning, " ");
|
|
25563
25648
|
console.log();
|
|
25564
25649
|
console.log(" " + bold("How NTRP calculates it"));
|
|
25565
|
-
|
|
25650
|
+
printWrapped(explainer.how_computed, " ");
|
|
25566
25651
|
for (const f of explainer.formula_lines) {
|
|
25567
25652
|
console.log(" " + paint("accent", f));
|
|
25568
25653
|
}
|