claude-presentation-master 3.9.0 → 4.1.0
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/README.md +32 -19
- package/bin/cli.js +2 -2
- package/dist/index.d.mts +44 -11
- package/dist/index.d.ts +44 -11
- package/dist/index.js +164 -137
- package/dist/index.mjs +164 -137
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -20,25 +20,38 @@
|
|
|
20
20
|
|
|
21
21
|
---
|
|
22
22
|
|
|
23
|
-
## What's New in
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
-
|
|
29
|
-
-
|
|
30
|
-
|
|
31
|
-
###
|
|
32
|
-
|
|
33
|
-
-
|
|
34
|
-
-
|
|
35
|
-
-
|
|
36
|
-
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
-
|
|
40
|
-
-
|
|
41
|
-
-
|
|
23
|
+
## What's New in v4.0.0 — True Knowledge-Driven Architecture
|
|
24
|
+
|
|
25
|
+
**The Knowledge Base now DRIVES everything at runtime — no more hardcoded specs.**
|
|
26
|
+
|
|
27
|
+
### Breaking Changes
|
|
28
|
+
- `PresentationEngineV2` now requires Knowledge Base YAML at runtime
|
|
29
|
+
- All design specs loaded from KB, not constants in code
|
|
30
|
+
|
|
31
|
+
### New Features
|
|
32
|
+
- **📚 Runtime KB Loading** — The 6,300+ line YAML knowledge base is parsed at runtime, not duplicated in code
|
|
33
|
+
- **🎯 H3 Action Title Extraction** — Markdown H3 headings become slide titles (McKinsey "so what" principle)
|
|
34
|
+
- **📊 Tables Preserved Correctly** — Tables stay as tables, never mangled into metric cards
|
|
35
|
+
- **🚫 No Orphan Slides** — Minimum 3 bullets per slide, balanced distribution
|
|
36
|
+
- **✅ 95+ Quality Threshold** — Engine fails if quality score below 95/100
|
|
37
|
+
|
|
38
|
+
### Knowledge Base Integration
|
|
39
|
+
- Word limits from `presentation_types.{type}.validation_rules.words_per_slide`
|
|
40
|
+
- Bullet limits from `presentation_types.{type}.validation_rules.bullets_per_slide`
|
|
41
|
+
- Theme from `presentation_types.{type}.color_palette`
|
|
42
|
+
- Experts from `presentation_types.{type}.primary_experts`
|
|
43
|
+
- Scoring weights from `presentation_types.{type}.scoring_weights`
|
|
44
|
+
|
|
45
|
+
### 7 Specialized Presentation Types
|
|
46
|
+
| Type | Theme | Words/Slide | Key Experts |
|
|
47
|
+
|------|-------|-------------|-------------|
|
|
48
|
+
| `ted_keynote` | Dark | 1-15 | Duarte, Reynolds, Anderson |
|
|
49
|
+
| `sales_pitch` | Modern | 10-30 | Cialdini, Heath |
|
|
50
|
+
| `consulting_deck` | McKinsey | 40-80 | Minto, McKinsey, BCG |
|
|
51
|
+
| `investment_banking` | McKinsey | 60-120 | Wall Street Prep |
|
|
52
|
+
| `investor_pitch` | Startup | 5-30 | Sequoia, YC |
|
|
53
|
+
| `technical_presentation` | Dark | 40-100 | Tufte, C4 Model |
|
|
54
|
+
| `all_hands` | Minimal | 15-40 | Internal Comms |
|
|
42
55
|
|
|
43
56
|
---
|
|
44
57
|
|
package/bin/cli.js
CHANGED
|
@@ -20,7 +20,7 @@ const args = process.argv.slice(2);
|
|
|
20
20
|
|
|
21
21
|
// Help text
|
|
22
22
|
const helpText = `
|
|
23
|
-
Claude Presentation Master
|
|
23
|
+
Claude Presentation Master v4.1.0
|
|
24
24
|
Generate world-class presentations using expert methodologies
|
|
25
25
|
|
|
26
26
|
100% FREE • Zero API Keys • Runs Locally
|
|
@@ -85,7 +85,7 @@ For more information: https://github.com/Stuinfla/claude-presentation-master
|
|
|
85
85
|
`;
|
|
86
86
|
|
|
87
87
|
// Version
|
|
88
|
-
const version = '
|
|
88
|
+
const version = '4.1.0';
|
|
89
89
|
|
|
90
90
|
// Parse arguments
|
|
91
91
|
function parseArgs(args) {
|
package/dist/index.d.mts
CHANGED
|
@@ -692,10 +692,27 @@ interface MetricData {
|
|
|
692
692
|
label: string;
|
|
693
693
|
trend?: 'up' | 'down' | 'neutral';
|
|
694
694
|
}
|
|
695
|
+
interface ModeConfig {
|
|
696
|
+
maxBulletsPerSlide: number;
|
|
697
|
+
maxWordsPerSlide: number;
|
|
698
|
+
minBulletsToKeep: number;
|
|
699
|
+
}
|
|
695
700
|
declare class SlideGeneratorV2 {
|
|
696
701
|
private config;
|
|
697
702
|
private presentationType;
|
|
703
|
+
/**
|
|
704
|
+
* Create a slide generator with default configs.
|
|
705
|
+
* For KB-driven configs, use createSlideGeneratorV2WithConfig() instead.
|
|
706
|
+
*/
|
|
698
707
|
constructor(presentationType?: PresentationType);
|
|
708
|
+
/**
|
|
709
|
+
* Override config with KB-loaded values at runtime.
|
|
710
|
+
*/
|
|
711
|
+
setConfig(config: ModeConfig): void;
|
|
712
|
+
/**
|
|
713
|
+
* Get current config (useful for debugging).
|
|
714
|
+
*/
|
|
715
|
+
getConfig(): ModeConfig;
|
|
699
716
|
/**
|
|
700
717
|
* Generate slides from markdown content.
|
|
701
718
|
* Simple, correct, no garbage.
|
|
@@ -904,17 +921,15 @@ declare function createRendererV2(presentationType?: PresentationType, themeOver
|
|
|
904
921
|
*
|
|
905
922
|
* This engine orchestrates the ENTIRE presentation creation flow:
|
|
906
923
|
* 1. Analyze content to detect presentation type
|
|
907
|
-
* 2. Load design specs from Knowledge Base
|
|
924
|
+
* 2. Load design specs from Knowledge Base (YAML)
|
|
908
925
|
* 3. Generate slides following expert methodologies
|
|
909
926
|
* 4. Enhance with images (optional, needs API key)
|
|
910
927
|
* 5. Review ruthlessly (must score 95/100+)
|
|
911
928
|
* 6. Output ONLY if quality passes
|
|
912
929
|
*
|
|
913
|
-
* The Knowledge Base drives EVERYTHING
|
|
914
|
-
* -
|
|
915
|
-
* -
|
|
916
|
-
* - Slide structure and word limits
|
|
917
|
-
* - Quality criteria and scoring
|
|
930
|
+
* CRITICAL: The Knowledge Base drives EVERYTHING.
|
|
931
|
+
* The KnowledgeGateway reads from presentation-knowledge.yaml at runtime.
|
|
932
|
+
* NO hardcoded fallbacks - if KB is missing data, we fail loudly.
|
|
918
933
|
*/
|
|
919
934
|
|
|
920
935
|
interface DesignSpecs {
|
|
@@ -923,18 +938,30 @@ interface DesignSpecs {
|
|
|
923
938
|
max: number;
|
|
924
939
|
ideal: number;
|
|
925
940
|
};
|
|
926
|
-
whitespace:
|
|
941
|
+
whitespace: {
|
|
942
|
+
min: number;
|
|
943
|
+
max?: number;
|
|
944
|
+
ideal: number;
|
|
945
|
+
};
|
|
927
946
|
bulletPoints: {
|
|
928
947
|
max: number;
|
|
929
948
|
};
|
|
930
949
|
fonts: {
|
|
931
|
-
title:
|
|
932
|
-
body:
|
|
933
|
-
|
|
950
|
+
title: string;
|
|
951
|
+
body: string;
|
|
952
|
+
maxFonts: number;
|
|
934
953
|
};
|
|
935
954
|
theme: ThemeStyle;
|
|
936
955
|
structure: string;
|
|
937
956
|
experts: string[];
|
|
957
|
+
actionTitlesRequired: boolean;
|
|
958
|
+
sourcesRequired: boolean;
|
|
959
|
+
scoringWeights: {
|
|
960
|
+
visual_quality: number;
|
|
961
|
+
content_quality: number;
|
|
962
|
+
expert_compliance: number;
|
|
963
|
+
accessibility: number;
|
|
964
|
+
};
|
|
938
965
|
}
|
|
939
966
|
interface SlideReview {
|
|
940
967
|
slideIndex: number;
|
|
@@ -977,11 +1004,15 @@ interface EngineResult {
|
|
|
977
1004
|
}
|
|
978
1005
|
declare class PresentationEngineV2 {
|
|
979
1006
|
private options;
|
|
1007
|
+
private kb;
|
|
980
1008
|
constructor(options?: EngineOptions);
|
|
981
1009
|
private log;
|
|
982
1010
|
/**
|
|
983
1011
|
* Generate a world-class presentation from markdown content.
|
|
984
1012
|
* Follows knowledge base specs and demands 95+ quality score.
|
|
1013
|
+
*
|
|
1014
|
+
* CRITICAL: All specs come from the Knowledge Base YAML at runtime.
|
|
1015
|
+
* No hardcoded fallbacks - if KB is missing data, we fail loudly.
|
|
985
1016
|
*/
|
|
986
1017
|
generate(markdown: string, title?: string): Promise<EngineResult>;
|
|
987
1018
|
/**
|
|
@@ -1207,6 +1238,8 @@ declare class SlideQualityReviewer {
|
|
|
1207
1238
|
private whitespaceRules;
|
|
1208
1239
|
private bulletLimit;
|
|
1209
1240
|
private glanceTestSeconds;
|
|
1241
|
+
private assessmentWeights;
|
|
1242
|
+
private _loggedWeights;
|
|
1210
1243
|
private hasCialdini;
|
|
1211
1244
|
private hasGestalt;
|
|
1212
1245
|
private hasTufteDataInk;
|
|
@@ -1753,7 +1786,7 @@ declare function runCodeQualityCheck(srcDir: string): Promise<boolean>;
|
|
|
1753
1786
|
* ALL decisions come from the Knowledge Base. NO hardcoded fallbacks.
|
|
1754
1787
|
*/
|
|
1755
1788
|
|
|
1756
|
-
declare const VERSION = "
|
|
1789
|
+
declare const VERSION = "4.1.0";
|
|
1757
1790
|
interface GenerateOptions {
|
|
1758
1791
|
/** Input content (Markdown, text, etc.) */
|
|
1759
1792
|
content: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -692,10 +692,27 @@ interface MetricData {
|
|
|
692
692
|
label: string;
|
|
693
693
|
trend?: 'up' | 'down' | 'neutral';
|
|
694
694
|
}
|
|
695
|
+
interface ModeConfig {
|
|
696
|
+
maxBulletsPerSlide: number;
|
|
697
|
+
maxWordsPerSlide: number;
|
|
698
|
+
minBulletsToKeep: number;
|
|
699
|
+
}
|
|
695
700
|
declare class SlideGeneratorV2 {
|
|
696
701
|
private config;
|
|
697
702
|
private presentationType;
|
|
703
|
+
/**
|
|
704
|
+
* Create a slide generator with default configs.
|
|
705
|
+
* For KB-driven configs, use createSlideGeneratorV2WithConfig() instead.
|
|
706
|
+
*/
|
|
698
707
|
constructor(presentationType?: PresentationType);
|
|
708
|
+
/**
|
|
709
|
+
* Override config with KB-loaded values at runtime.
|
|
710
|
+
*/
|
|
711
|
+
setConfig(config: ModeConfig): void;
|
|
712
|
+
/**
|
|
713
|
+
* Get current config (useful for debugging).
|
|
714
|
+
*/
|
|
715
|
+
getConfig(): ModeConfig;
|
|
699
716
|
/**
|
|
700
717
|
* Generate slides from markdown content.
|
|
701
718
|
* Simple, correct, no garbage.
|
|
@@ -904,17 +921,15 @@ declare function createRendererV2(presentationType?: PresentationType, themeOver
|
|
|
904
921
|
*
|
|
905
922
|
* This engine orchestrates the ENTIRE presentation creation flow:
|
|
906
923
|
* 1. Analyze content to detect presentation type
|
|
907
|
-
* 2. Load design specs from Knowledge Base
|
|
924
|
+
* 2. Load design specs from Knowledge Base (YAML)
|
|
908
925
|
* 3. Generate slides following expert methodologies
|
|
909
926
|
* 4. Enhance with images (optional, needs API key)
|
|
910
927
|
* 5. Review ruthlessly (must score 95/100+)
|
|
911
928
|
* 6. Output ONLY if quality passes
|
|
912
929
|
*
|
|
913
|
-
* The Knowledge Base drives EVERYTHING
|
|
914
|
-
* -
|
|
915
|
-
* -
|
|
916
|
-
* - Slide structure and word limits
|
|
917
|
-
* - Quality criteria and scoring
|
|
930
|
+
* CRITICAL: The Knowledge Base drives EVERYTHING.
|
|
931
|
+
* The KnowledgeGateway reads from presentation-knowledge.yaml at runtime.
|
|
932
|
+
* NO hardcoded fallbacks - if KB is missing data, we fail loudly.
|
|
918
933
|
*/
|
|
919
934
|
|
|
920
935
|
interface DesignSpecs {
|
|
@@ -923,18 +938,30 @@ interface DesignSpecs {
|
|
|
923
938
|
max: number;
|
|
924
939
|
ideal: number;
|
|
925
940
|
};
|
|
926
|
-
whitespace:
|
|
941
|
+
whitespace: {
|
|
942
|
+
min: number;
|
|
943
|
+
max?: number;
|
|
944
|
+
ideal: number;
|
|
945
|
+
};
|
|
927
946
|
bulletPoints: {
|
|
928
947
|
max: number;
|
|
929
948
|
};
|
|
930
949
|
fonts: {
|
|
931
|
-
title:
|
|
932
|
-
body:
|
|
933
|
-
|
|
950
|
+
title: string;
|
|
951
|
+
body: string;
|
|
952
|
+
maxFonts: number;
|
|
934
953
|
};
|
|
935
954
|
theme: ThemeStyle;
|
|
936
955
|
structure: string;
|
|
937
956
|
experts: string[];
|
|
957
|
+
actionTitlesRequired: boolean;
|
|
958
|
+
sourcesRequired: boolean;
|
|
959
|
+
scoringWeights: {
|
|
960
|
+
visual_quality: number;
|
|
961
|
+
content_quality: number;
|
|
962
|
+
expert_compliance: number;
|
|
963
|
+
accessibility: number;
|
|
964
|
+
};
|
|
938
965
|
}
|
|
939
966
|
interface SlideReview {
|
|
940
967
|
slideIndex: number;
|
|
@@ -977,11 +1004,15 @@ interface EngineResult {
|
|
|
977
1004
|
}
|
|
978
1005
|
declare class PresentationEngineV2 {
|
|
979
1006
|
private options;
|
|
1007
|
+
private kb;
|
|
980
1008
|
constructor(options?: EngineOptions);
|
|
981
1009
|
private log;
|
|
982
1010
|
/**
|
|
983
1011
|
* Generate a world-class presentation from markdown content.
|
|
984
1012
|
* Follows knowledge base specs and demands 95+ quality score.
|
|
1013
|
+
*
|
|
1014
|
+
* CRITICAL: All specs come from the Knowledge Base YAML at runtime.
|
|
1015
|
+
* No hardcoded fallbacks - if KB is missing data, we fail loudly.
|
|
985
1016
|
*/
|
|
986
1017
|
generate(markdown: string, title?: string): Promise<EngineResult>;
|
|
987
1018
|
/**
|
|
@@ -1207,6 +1238,8 @@ declare class SlideQualityReviewer {
|
|
|
1207
1238
|
private whitespaceRules;
|
|
1208
1239
|
private bulletLimit;
|
|
1209
1240
|
private glanceTestSeconds;
|
|
1241
|
+
private assessmentWeights;
|
|
1242
|
+
private _loggedWeights;
|
|
1210
1243
|
private hasCialdini;
|
|
1211
1244
|
private hasGestalt;
|
|
1212
1245
|
private hasTufteDataInk;
|
|
@@ -1753,7 +1786,7 @@ declare function runCodeQualityCheck(srcDir: string): Promise<boolean>;
|
|
|
1753
1786
|
* ALL decisions come from the Knowledge Base. NO hardcoded fallbacks.
|
|
1754
1787
|
*/
|
|
1755
1788
|
|
|
1756
|
-
declare const VERSION = "
|
|
1789
|
+
declare const VERSION = "4.1.0";
|
|
1757
1790
|
interface GenerateOptions {
|
|
1758
1791
|
/** Input content (Markdown, text, etc.) */
|
|
1759
1792
|
content: string;
|
package/dist/index.js
CHANGED
|
@@ -93756,21 +93756,52 @@ async function initSlideGenerator() {
|
|
|
93756
93756
|
|
|
93757
93757
|
// src/core/SlideGeneratorV2.ts
|
|
93758
93758
|
var import_marked = require("marked");
|
|
93759
|
-
var
|
|
93760
|
-
// Consulting decks: 40-80 words per slide is NORMAL
|
|
93759
|
+
var DEFAULT_CONFIGS = {
|
|
93760
|
+
// Consulting decks: 40-80 words per slide is NORMAL (from KB)
|
|
93761
93761
|
consulting_deck: {
|
|
93762
93762
|
maxBulletsPerSlide: 7,
|
|
93763
|
-
maxWordsPerSlide:
|
|
93764
|
-
//
|
|
93763
|
+
maxWordsPerSlide: 80,
|
|
93764
|
+
// KB: words_per_slide.max
|
|
93765
|
+
minBulletsToKeep: 3
|
|
93766
|
+
},
|
|
93767
|
+
investment_banking: {
|
|
93768
|
+
maxBulletsPerSlide: 8,
|
|
93769
|
+
maxWordsPerSlide: 120,
|
|
93770
|
+
// KB: words_per_slide.max
|
|
93765
93771
|
minBulletsToKeep: 3
|
|
93766
93772
|
},
|
|
93767
|
-
// Keynotes: fewer words, more impact
|
|
93768
|
-
|
|
93773
|
+
// Keynotes: fewer words, more impact (from KB)
|
|
93774
|
+
ted_keynote: {
|
|
93769
93775
|
maxBulletsPerSlide: 4,
|
|
93776
|
+
maxWordsPerSlide: 15,
|
|
93777
|
+
// KB: words_per_slide.max
|
|
93778
|
+
minBulletsToKeep: 2
|
|
93779
|
+
},
|
|
93780
|
+
sales_pitch: {
|
|
93781
|
+
maxBulletsPerSlide: 5,
|
|
93770
93782
|
maxWordsPerSlide: 30,
|
|
93783
|
+
// KB: words_per_slide.max
|
|
93784
|
+
minBulletsToKeep: 2
|
|
93785
|
+
},
|
|
93786
|
+
investor_pitch: {
|
|
93787
|
+
maxBulletsPerSlide: 5,
|
|
93788
|
+
maxWordsPerSlide: 50,
|
|
93789
|
+
// KB: words_per_slide.max
|
|
93790
|
+
minBulletsToKeep: 2
|
|
93791
|
+
},
|
|
93792
|
+
technical_presentation: {
|
|
93793
|
+
maxBulletsPerSlide: 6,
|
|
93794
|
+
maxWordsPerSlide: 100,
|
|
93795
|
+
// KB: words_per_slide.max
|
|
93796
|
+
minBulletsToKeep: 3
|
|
93797
|
+
},
|
|
93798
|
+
all_hands: {
|
|
93799
|
+
maxBulletsPerSlide: 5,
|
|
93800
|
+
maxWordsPerSlide: 40,
|
|
93801
|
+
// KB: words_per_slide.max
|
|
93771
93802
|
minBulletsToKeep: 2
|
|
93772
93803
|
},
|
|
93773
|
-
// Default:
|
|
93804
|
+
// Default: fallback
|
|
93774
93805
|
default: {
|
|
93775
93806
|
maxBulletsPerSlide: 6,
|
|
93776
93807
|
maxWordsPerSlide: 80,
|
|
@@ -93780,9 +93811,25 @@ var MODE_CONFIGS = {
|
|
|
93780
93811
|
var SlideGeneratorV2 = class {
|
|
93781
93812
|
config;
|
|
93782
93813
|
presentationType;
|
|
93814
|
+
/**
|
|
93815
|
+
* Create a slide generator with default configs.
|
|
93816
|
+
* For KB-driven configs, use createSlideGeneratorV2WithConfig() instead.
|
|
93817
|
+
*/
|
|
93783
93818
|
constructor(presentationType = "consulting_deck") {
|
|
93784
93819
|
this.presentationType = presentationType;
|
|
93785
|
-
this.config =
|
|
93820
|
+
this.config = DEFAULT_CONFIGS[presentationType] || DEFAULT_CONFIGS.default;
|
|
93821
|
+
}
|
|
93822
|
+
/**
|
|
93823
|
+
* Override config with KB-loaded values at runtime.
|
|
93824
|
+
*/
|
|
93825
|
+
setConfig(config2) {
|
|
93826
|
+
this.config = config2;
|
|
93827
|
+
}
|
|
93828
|
+
/**
|
|
93829
|
+
* Get current config (useful for debugging).
|
|
93830
|
+
*/
|
|
93831
|
+
getConfig() {
|
|
93832
|
+
return this.config;
|
|
93786
93833
|
}
|
|
93787
93834
|
/**
|
|
93788
93835
|
* Generate slides from markdown content.
|
|
@@ -95505,133 +95552,69 @@ function createRendererV2(presentationType = "consulting_deck", themeOverride) {
|
|
|
95505
95552
|
|
|
95506
95553
|
// src/core/PresentationEngineV2.ts
|
|
95507
95554
|
var import_fs9 = require("fs");
|
|
95508
|
-
var
|
|
95509
|
-
|
|
95510
|
-
|
|
95511
|
-
|
|
95512
|
-
|
|
95513
|
-
|
|
95514
|
-
fonts: { title: 72, body: 42, minimum: 36 },
|
|
95515
|
-
theme: "dark",
|
|
95516
|
-
structure: "Sparkline (What Is / What Could Be)",
|
|
95517
|
-
experts: ["Nancy Duarte", "Garr Reynolds", "Carmine Gallo", "Chris Anderson"]
|
|
95518
|
-
},
|
|
95519
|
-
// Sales Pitch - Persuasive, emotional, clear CTA
|
|
95520
|
-
sales_pitch: {
|
|
95521
|
-
wordsPerSlide: { min: 10, max: 35, ideal: 20 },
|
|
95522
|
-
whitespace: "35%+",
|
|
95523
|
-
bulletPoints: { max: 4 },
|
|
95524
|
-
fonts: { title: 56, body: 32, minimum: 28 },
|
|
95525
|
-
theme: "dark",
|
|
95526
|
-
structure: "SPIN (Situation, Problem, Implication, Need-Payoff)",
|
|
95527
|
-
experts: ["Cialdini", "Challenger Sale", "Oren Klaff"]
|
|
95528
|
-
},
|
|
95529
|
-
// Consulting Deck - Data-driven, McKinsey style
|
|
95530
|
-
consulting_deck: {
|
|
95531
|
-
wordsPerSlide: { min: 40, max: 80, ideal: 60 },
|
|
95532
|
-
whitespace: "25-30%",
|
|
95533
|
-
bulletPoints: { max: 7 },
|
|
95534
|
-
fonts: { title: 44, body: 22, minimum: 18 },
|
|
95535
|
-
theme: "mckinsey",
|
|
95536
|
-
structure: "Pyramid Principle (MECE, SCR)",
|
|
95537
|
-
experts: ["Barbara Minto", "McKinsey", "BCG", "Bain"]
|
|
95538
|
-
},
|
|
95539
|
-
// Investment Banking - Dense, financial, formal
|
|
95540
|
-
investment_banking: {
|
|
95541
|
-
wordsPerSlide: { min: 60, max: 120, ideal: 90 },
|
|
95542
|
-
whitespace: "20-25%",
|
|
95543
|
-
bulletPoints: { max: 8 },
|
|
95544
|
-
fonts: { title: 28, body: 12, minimum: 10 },
|
|
95545
|
-
theme: "mckinsey",
|
|
95546
|
-
structure: "Situation-Complication-Hypothesis",
|
|
95547
|
-
experts: ["Wall Street Prep", "Analyst Academy"]
|
|
95548
|
-
},
|
|
95549
|
-
// Investor Pitch - Concise, startup-friendly
|
|
95550
|
-
investor_pitch: {
|
|
95551
|
-
wordsPerSlide: { min: 5, max: 30, ideal: 15 },
|
|
95552
|
-
whitespace: "35%+",
|
|
95553
|
-
bulletPoints: { max: 4 },
|
|
95554
|
-
fonts: { title: 48, body: 28, minimum: 24 },
|
|
95555
|
-
theme: "startup",
|
|
95556
|
-
structure: "Problem \u2192 Solution \u2192 Market \u2192 Traction \u2192 Team \u2192 Ask",
|
|
95557
|
-
experts: ["Sequoia", "Y Combinator", "DocSend"]
|
|
95558
|
-
},
|
|
95559
|
-
// Technical Presentation - Clear diagrams, code-friendly
|
|
95560
|
-
technical_presentation: {
|
|
95561
|
-
wordsPerSlide: { min: 40, max: 100, ideal: 75 },
|
|
95562
|
-
whitespace: "25%+",
|
|
95563
|
-
bulletPoints: { max: 6 },
|
|
95564
|
-
fonts: { title: 44, body: 20, minimum: 14 },
|
|
95565
|
-
theme: "dark",
|
|
95566
|
-
structure: "TL;DR \u2192 Problem \u2192 Architecture \u2192 Tradeoffs \u2192 Next Steps",
|
|
95567
|
-
experts: ["Edward Tufte", "C4 Model", "Google Design Docs"]
|
|
95568
|
-
},
|
|
95569
|
-
// All Hands - Accessible, clear, motivational
|
|
95570
|
-
all_hands: {
|
|
95571
|
-
wordsPerSlide: { min: 15, max: 40, ideal: 25 },
|
|
95572
|
-
whitespace: "30%+",
|
|
95573
|
-
bulletPoints: { max: 5 },
|
|
95574
|
-
fonts: { title: 52, body: 28, minimum: 24 },
|
|
95575
|
-
theme: "minimal",
|
|
95576
|
-
structure: "Updates \u2192 Wins \u2192 Challenges \u2192 What's Next",
|
|
95577
|
-
experts: ["Internal Communications Best Practices"]
|
|
95578
|
-
}
|
|
95555
|
+
var PALETTE_TO_THEME = {
|
|
95556
|
+
dark_executive: "dark",
|
|
95557
|
+
modern_business: "startup",
|
|
95558
|
+
consulting_classic: "mckinsey",
|
|
95559
|
+
executive_professional: "mckinsey",
|
|
95560
|
+
strategy_growth: "minimal"
|
|
95579
95561
|
};
|
|
95580
|
-
|
|
95581
|
-
|
|
95582
|
-
|
|
95583
|
-
|
|
95584
|
-
|
|
95585
|
-
|
|
95586
|
-
|
|
95587
|
-
|
|
95588
|
-
|
|
95589
|
-
|
|
95590
|
-
|
|
95591
|
-
|
|
95592
|
-
|
|
95593
|
-
|
|
95594
|
-
}
|
|
95595
|
-
|
|
95596
|
-
|
|
95597
|
-
|
|
95598
|
-
wordLimitStrict: false,
|
|
95599
|
-
// Consulting allows denser slides
|
|
95600
|
-
requireActionTitles: true,
|
|
95601
|
-
// Titles should state the "so what"
|
|
95602
|
-
requireDataSources: true
|
|
95603
|
-
},
|
|
95604
|
-
investment_banking: {
|
|
95605
|
-
glanceTestSeconds: 10,
|
|
95606
|
-
minScore: 95,
|
|
95607
|
-
wordLimitStrict: false,
|
|
95608
|
-
requireActionTitles: true,
|
|
95609
|
-
requireDataSources: true
|
|
95610
|
-
},
|
|
95611
|
-
investor_pitch: {
|
|
95612
|
-
glanceTestSeconds: 3,
|
|
95613
|
-
minScore: 95,
|
|
95614
|
-
wordLimitStrict: true,
|
|
95615
|
-
requireActionTitles: true,
|
|
95616
|
-
requireDataSources: true
|
|
95617
|
-
},
|
|
95618
|
-
technical_presentation: {
|
|
95619
|
-
glanceTestSeconds: 5,
|
|
95620
|
-
minScore: 95,
|
|
95621
|
-
wordLimitStrict: false,
|
|
95622
|
-
requireActionTitles: false,
|
|
95623
|
-
requireDataSources: true
|
|
95624
|
-
},
|
|
95625
|
-
all_hands: {
|
|
95626
|
-
glanceTestSeconds: 3,
|
|
95627
|
-
minScore: 95,
|
|
95628
|
-
wordLimitStrict: true,
|
|
95629
|
-
requireActionTitles: false,
|
|
95630
|
-
requireDataSources: false
|
|
95562
|
+
async function loadDesignSpecsFromKB(kb, type) {
|
|
95563
|
+
const typeConfig = kb.queryRequired(`presentation_types.${type}`);
|
|
95564
|
+
const validationRules = typeConfig.value.validation_rules;
|
|
95565
|
+
const wordsPerSlide = validationRules.words_per_slide;
|
|
95566
|
+
const whitespace = validationRules.whitespace;
|
|
95567
|
+
const bulletsPerSlide = validationRules.bullets_per_slide;
|
|
95568
|
+
const typography = typeConfig.value.typography;
|
|
95569
|
+
const primaryExperts = typeConfig.value.primary_experts;
|
|
95570
|
+
const colorPalette = typeConfig.value.color_palette || "consulting_classic";
|
|
95571
|
+
const theme = PALETTE_TO_THEME[colorPalette] || "mckinsey";
|
|
95572
|
+
const scoringWeights = typeConfig.value.scoring_weights;
|
|
95573
|
+
let structure = "General presentation structure";
|
|
95574
|
+
if (primaryExperts.some((e) => e.includes("Minto") || e.includes("McKinsey"))) {
|
|
95575
|
+
structure = "Pyramid Principle (MECE, SCR)";
|
|
95576
|
+
} else if (primaryExperts.some((e) => e.includes("Duarte"))) {
|
|
95577
|
+
structure = "Sparkline (What Is / What Could Be)";
|
|
95578
|
+
} else if (primaryExperts.some((e) => e.includes("Cialdini"))) {
|
|
95579
|
+
structure = "Persuasion-driven (SPIN, Challenger)";
|
|
95631
95580
|
}
|
|
95632
|
-
|
|
95581
|
+
return {
|
|
95582
|
+
wordsPerSlide,
|
|
95583
|
+
whitespace,
|
|
95584
|
+
bulletPoints: { max: bulletsPerSlide?.max || 5 },
|
|
95585
|
+
fonts: {
|
|
95586
|
+
title: typography?.titles || "44px, Bold",
|
|
95587
|
+
body: typography?.body || "22px",
|
|
95588
|
+
maxFonts: typography?.max_fonts || 2
|
|
95589
|
+
},
|
|
95590
|
+
theme,
|
|
95591
|
+
structure,
|
|
95592
|
+
experts: primaryExperts,
|
|
95593
|
+
actionTitlesRequired: validationRules.action_titles_required || false,
|
|
95594
|
+
sourcesRequired: validationRules.sources_required || false,
|
|
95595
|
+
scoringWeights: scoringWeights || {
|
|
95596
|
+
visual_quality: 30,
|
|
95597
|
+
content_quality: 30,
|
|
95598
|
+
expert_compliance: 30,
|
|
95599
|
+
accessibility: 10
|
|
95600
|
+
}
|
|
95601
|
+
};
|
|
95602
|
+
}
|
|
95603
|
+
function getQualityCriteria(specs, type) {
|
|
95604
|
+
const isKeynote = type === "ted_keynote" || type === "sales_pitch";
|
|
95605
|
+
const isConsulting = type === "consulting_deck" || type === "investment_banking";
|
|
95606
|
+
return {
|
|
95607
|
+
glanceTestSeconds: isKeynote ? 3 : isConsulting ? 5 : 3,
|
|
95608
|
+
minScore: 95,
|
|
95609
|
+
wordLimitStrict: isKeynote,
|
|
95610
|
+
// Keynotes have strict word limits
|
|
95611
|
+
requireActionTitles: specs.actionTitlesRequired,
|
|
95612
|
+
requireDataSources: specs.sourcesRequired
|
|
95613
|
+
};
|
|
95614
|
+
}
|
|
95633
95615
|
var PresentationEngineV2 = class {
|
|
95634
95616
|
options;
|
|
95617
|
+
kb = null;
|
|
95635
95618
|
constructor(options = {}) {
|
|
95636
95619
|
this.options = {
|
|
95637
95620
|
presentationType: options.presentationType || "consulting_deck",
|
|
@@ -95650,19 +95633,26 @@ var PresentationEngineV2 = class {
|
|
|
95650
95633
|
/**
|
|
95651
95634
|
* Generate a world-class presentation from markdown content.
|
|
95652
95635
|
* Follows knowledge base specs and demands 95+ quality score.
|
|
95636
|
+
*
|
|
95637
|
+
* CRITICAL: All specs come from the Knowledge Base YAML at runtime.
|
|
95638
|
+
* No hardcoded fallbacks - if KB is missing data, we fail loudly.
|
|
95653
95639
|
*/
|
|
95654
95640
|
async generate(markdown, title) {
|
|
95655
95641
|
const warnings = [];
|
|
95642
|
+
this.log("Step 0: Loading Knowledge Base...");
|
|
95643
|
+
this.kb = await initKB();
|
|
95644
|
+
this.log(` KB v${this.kb.getVersion()} loaded`);
|
|
95656
95645
|
this.log("Step 1: Detecting presentation type...");
|
|
95657
95646
|
const detectedType = this.detectPresentationType(markdown);
|
|
95658
95647
|
const presentationType = this.options.presentationType || detectedType;
|
|
95659
95648
|
this.log(` Using type: ${presentationType} (detected: ${detectedType})`);
|
|
95660
95649
|
this.log("Step 2: Loading design specs from Knowledge Base...");
|
|
95661
|
-
const designSpecs =
|
|
95662
|
-
const qualityCriteria =
|
|
95650
|
+
const designSpecs = await loadDesignSpecsFromKB(this.kb, presentationType);
|
|
95651
|
+
const qualityCriteria = getQualityCriteria(designSpecs, presentationType);
|
|
95663
95652
|
this.log(` Theme: ${designSpecs.theme}`);
|
|
95664
95653
|
this.log(` Structure: ${designSpecs.structure}`);
|
|
95665
95654
|
this.log(` Words/slide: ${designSpecs.wordsPerSlide.min}-${designSpecs.wordsPerSlide.max}`);
|
|
95655
|
+
this.log(` Experts: ${designSpecs.experts.slice(0, 2).join(", ")}...`);
|
|
95666
95656
|
this.log("Step 3: Generating slides...");
|
|
95667
95657
|
const generator = createSlideGeneratorV2(presentationType);
|
|
95668
95658
|
let slides = generator.generate(markdown, title);
|
|
@@ -95990,7 +95980,6 @@ SUCCESS: Generated ${slides.length} slides scoring ${review.overallScore}/100`);
|
|
|
95990
95980
|
* Assess the flow and narrative structure of the deck.
|
|
95991
95981
|
*/
|
|
95992
95982
|
assessFlow(slides, type) {
|
|
95993
|
-
const specs = KNOWLEDGE_BASE[type];
|
|
95994
95983
|
let score = 100;
|
|
95995
95984
|
const types = slides.map((s) => s.type);
|
|
95996
95985
|
if (types[0] !== "title") score -= 10;
|
|
@@ -96072,7 +96061,7 @@ Output: ${htmlPath}`);
|
|
|
96072
96061
|
}
|
|
96073
96062
|
|
|
96074
96063
|
// src/qa/SlideQualityReviewer.ts
|
|
96075
|
-
var
|
|
96064
|
+
var DEFAULT_ASSESSMENT_WEIGHTS = {
|
|
96076
96065
|
visualImpact: 0.25,
|
|
96077
96066
|
contentClarity: 0.2,
|
|
96078
96067
|
layoutBalance: 0.15,
|
|
@@ -96081,6 +96070,29 @@ var ASSESSMENT_WEIGHTS = {
|
|
|
96081
96070
|
colorHarmony: 0.1,
|
|
96082
96071
|
audienceAppropriate: 0.05
|
|
96083
96072
|
};
|
|
96073
|
+
function computeWeightsFromKB(kbWeights) {
|
|
96074
|
+
const totalKB = kbWeights.visual_quality + kbWeights.content_quality + kbWeights.expert_compliance + kbWeights.accessibility;
|
|
96075
|
+
const vq = kbWeights.visual_quality / totalKB;
|
|
96076
|
+
const cq = kbWeights.content_quality / totalKB;
|
|
96077
|
+
const ec = kbWeights.expert_compliance / totalKB;
|
|
96078
|
+
const ac = kbWeights.accessibility / totalKB;
|
|
96079
|
+
return {
|
|
96080
|
+
visualImpact: vq * 0.6,
|
|
96081
|
+
// 60% of visual_quality
|
|
96082
|
+
colorHarmony: vq * 0.4,
|
|
96083
|
+
// 40% of visual_quality
|
|
96084
|
+
contentClarity: cq * 0.8,
|
|
96085
|
+
// 80% of content_quality
|
|
96086
|
+
audienceAppropriate: cq * 0.2,
|
|
96087
|
+
// 20% of content_quality
|
|
96088
|
+
layoutBalance: ec * 0.5,
|
|
96089
|
+
// 50% of expert_compliance
|
|
96090
|
+
typographyHierarchy: ec * 0.5,
|
|
96091
|
+
// 50% of expert_compliance
|
|
96092
|
+
whitespaceUsage: ac
|
|
96093
|
+
// 100% of accessibility
|
|
96094
|
+
};
|
|
96095
|
+
}
|
|
96084
96096
|
var SlideQualityReviewer = class {
|
|
96085
96097
|
kb;
|
|
96086
96098
|
initialized = false;
|
|
@@ -96089,6 +96101,9 @@ var SlideQualityReviewer = class {
|
|
|
96089
96101
|
whitespaceRules;
|
|
96090
96102
|
bulletLimit;
|
|
96091
96103
|
glanceTestSeconds;
|
|
96104
|
+
// KB-loaded scoring weights (computed from KB per presentation type)
|
|
96105
|
+
assessmentWeights = DEFAULT_ASSESSMENT_WEIGHTS;
|
|
96106
|
+
_loggedWeights = null;
|
|
96092
96107
|
// Expert rules from KB
|
|
96093
96108
|
hasCialdini = false;
|
|
96094
96109
|
hasGestalt = false;
|
|
@@ -96119,7 +96134,7 @@ var SlideQualityReviewer = class {
|
|
|
96119
96134
|
};
|
|
96120
96135
|
let totalScore = 0;
|
|
96121
96136
|
for (const [key, assessment] of Object.entries(assessments)) {
|
|
96122
|
-
const weight =
|
|
96137
|
+
const weight = this.assessmentWeights[key];
|
|
96123
96138
|
totalScore += assessment.score * weight;
|
|
96124
96139
|
}
|
|
96125
96140
|
const score = Math.round(totalScore);
|
|
@@ -96174,6 +96189,18 @@ var SlideQualityReviewer = class {
|
|
|
96174
96189
|
this.wordLimits = wordLimitsResult.value;
|
|
96175
96190
|
const whitespaceResult = this.kb.getWhitespaceRules(type);
|
|
96176
96191
|
this.whitespaceRules = whitespaceResult.value;
|
|
96192
|
+
try {
|
|
96193
|
+
const weightsResult = this.kb.getScoringWeights(type);
|
|
96194
|
+
const kbWeights = weightsResult.value;
|
|
96195
|
+
this.assessmentWeights = computeWeightsFromKB(kbWeights);
|
|
96196
|
+
if (!this._loggedWeights?.has(type)) {
|
|
96197
|
+
console.log(`[QA] Loaded scoring weights for ${type}: visual=${kbWeights.visual_quality}%, content=${kbWeights.content_quality}%, expert=${kbWeights.expert_compliance}%, accessibility=${kbWeights.accessibility}%`);
|
|
96198
|
+
if (!this._loggedWeights) this._loggedWeights = /* @__PURE__ */ new Set();
|
|
96199
|
+
this._loggedWeights.add(type);
|
|
96200
|
+
}
|
|
96201
|
+
} catch {
|
|
96202
|
+
this.assessmentWeights = DEFAULT_ASSESSMENT_WEIGHTS;
|
|
96203
|
+
}
|
|
96177
96204
|
try {
|
|
96178
96205
|
const glanceResult = this.kb.getGlanceTest();
|
|
96179
96206
|
this.glanceTestSeconds = 3;
|
|
@@ -99467,7 +99494,7 @@ if (typeof process !== "undefined" && process.argv[1]?.includes("CodeQualityVali
|
|
|
99467
99494
|
}
|
|
99468
99495
|
|
|
99469
99496
|
// src/index.ts
|
|
99470
|
-
var VERSION = "
|
|
99497
|
+
var VERSION = "4.1.0";
|
|
99471
99498
|
async function generate(options) {
|
|
99472
99499
|
const {
|
|
99473
99500
|
content,
|
package/dist/index.mjs
CHANGED
|
@@ -2040,21 +2040,52 @@ async function initSlideGenerator() {
|
|
|
2040
2040
|
|
|
2041
2041
|
// src/core/SlideGeneratorV2.ts
|
|
2042
2042
|
import { marked } from "marked";
|
|
2043
|
-
var
|
|
2044
|
-
// Consulting decks: 40-80 words per slide is NORMAL
|
|
2043
|
+
var DEFAULT_CONFIGS = {
|
|
2044
|
+
// Consulting decks: 40-80 words per slide is NORMAL (from KB)
|
|
2045
2045
|
consulting_deck: {
|
|
2046
2046
|
maxBulletsPerSlide: 7,
|
|
2047
|
-
maxWordsPerSlide:
|
|
2048
|
-
//
|
|
2047
|
+
maxWordsPerSlide: 80,
|
|
2048
|
+
// KB: words_per_slide.max
|
|
2049
|
+
minBulletsToKeep: 3
|
|
2050
|
+
},
|
|
2051
|
+
investment_banking: {
|
|
2052
|
+
maxBulletsPerSlide: 8,
|
|
2053
|
+
maxWordsPerSlide: 120,
|
|
2054
|
+
// KB: words_per_slide.max
|
|
2049
2055
|
minBulletsToKeep: 3
|
|
2050
2056
|
},
|
|
2051
|
-
// Keynotes: fewer words, more impact
|
|
2052
|
-
|
|
2057
|
+
// Keynotes: fewer words, more impact (from KB)
|
|
2058
|
+
ted_keynote: {
|
|
2053
2059
|
maxBulletsPerSlide: 4,
|
|
2060
|
+
maxWordsPerSlide: 15,
|
|
2061
|
+
// KB: words_per_slide.max
|
|
2062
|
+
minBulletsToKeep: 2
|
|
2063
|
+
},
|
|
2064
|
+
sales_pitch: {
|
|
2065
|
+
maxBulletsPerSlide: 5,
|
|
2054
2066
|
maxWordsPerSlide: 30,
|
|
2067
|
+
// KB: words_per_slide.max
|
|
2068
|
+
minBulletsToKeep: 2
|
|
2069
|
+
},
|
|
2070
|
+
investor_pitch: {
|
|
2071
|
+
maxBulletsPerSlide: 5,
|
|
2072
|
+
maxWordsPerSlide: 50,
|
|
2073
|
+
// KB: words_per_slide.max
|
|
2074
|
+
minBulletsToKeep: 2
|
|
2075
|
+
},
|
|
2076
|
+
technical_presentation: {
|
|
2077
|
+
maxBulletsPerSlide: 6,
|
|
2078
|
+
maxWordsPerSlide: 100,
|
|
2079
|
+
// KB: words_per_slide.max
|
|
2080
|
+
minBulletsToKeep: 3
|
|
2081
|
+
},
|
|
2082
|
+
all_hands: {
|
|
2083
|
+
maxBulletsPerSlide: 5,
|
|
2084
|
+
maxWordsPerSlide: 40,
|
|
2085
|
+
// KB: words_per_slide.max
|
|
2055
2086
|
minBulletsToKeep: 2
|
|
2056
2087
|
},
|
|
2057
|
-
// Default:
|
|
2088
|
+
// Default: fallback
|
|
2058
2089
|
default: {
|
|
2059
2090
|
maxBulletsPerSlide: 6,
|
|
2060
2091
|
maxWordsPerSlide: 80,
|
|
@@ -2064,9 +2095,25 @@ var MODE_CONFIGS = {
|
|
|
2064
2095
|
var SlideGeneratorV2 = class {
|
|
2065
2096
|
config;
|
|
2066
2097
|
presentationType;
|
|
2098
|
+
/**
|
|
2099
|
+
* Create a slide generator with default configs.
|
|
2100
|
+
* For KB-driven configs, use createSlideGeneratorV2WithConfig() instead.
|
|
2101
|
+
*/
|
|
2067
2102
|
constructor(presentationType = "consulting_deck") {
|
|
2068
2103
|
this.presentationType = presentationType;
|
|
2069
|
-
this.config =
|
|
2104
|
+
this.config = DEFAULT_CONFIGS[presentationType] || DEFAULT_CONFIGS.default;
|
|
2105
|
+
}
|
|
2106
|
+
/**
|
|
2107
|
+
* Override config with KB-loaded values at runtime.
|
|
2108
|
+
*/
|
|
2109
|
+
setConfig(config) {
|
|
2110
|
+
this.config = config;
|
|
2111
|
+
}
|
|
2112
|
+
/**
|
|
2113
|
+
* Get current config (useful for debugging).
|
|
2114
|
+
*/
|
|
2115
|
+
getConfig() {
|
|
2116
|
+
return this.config;
|
|
2070
2117
|
}
|
|
2071
2118
|
/**
|
|
2072
2119
|
* Generate slides from markdown content.
|
|
@@ -3789,133 +3836,69 @@ function createRendererV2(presentationType = "consulting_deck", themeOverride) {
|
|
|
3789
3836
|
|
|
3790
3837
|
// src/core/PresentationEngineV2.ts
|
|
3791
3838
|
import { writeFileSync as writeFileSync2 } from "fs";
|
|
3792
|
-
var
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
fonts: { title: 72, body: 42, minimum: 36 },
|
|
3799
|
-
theme: "dark",
|
|
3800
|
-
structure: "Sparkline (What Is / What Could Be)",
|
|
3801
|
-
experts: ["Nancy Duarte", "Garr Reynolds", "Carmine Gallo", "Chris Anderson"]
|
|
3802
|
-
},
|
|
3803
|
-
// Sales Pitch - Persuasive, emotional, clear CTA
|
|
3804
|
-
sales_pitch: {
|
|
3805
|
-
wordsPerSlide: { min: 10, max: 35, ideal: 20 },
|
|
3806
|
-
whitespace: "35%+",
|
|
3807
|
-
bulletPoints: { max: 4 },
|
|
3808
|
-
fonts: { title: 56, body: 32, minimum: 28 },
|
|
3809
|
-
theme: "dark",
|
|
3810
|
-
structure: "SPIN (Situation, Problem, Implication, Need-Payoff)",
|
|
3811
|
-
experts: ["Cialdini", "Challenger Sale", "Oren Klaff"]
|
|
3812
|
-
},
|
|
3813
|
-
// Consulting Deck - Data-driven, McKinsey style
|
|
3814
|
-
consulting_deck: {
|
|
3815
|
-
wordsPerSlide: { min: 40, max: 80, ideal: 60 },
|
|
3816
|
-
whitespace: "25-30%",
|
|
3817
|
-
bulletPoints: { max: 7 },
|
|
3818
|
-
fonts: { title: 44, body: 22, minimum: 18 },
|
|
3819
|
-
theme: "mckinsey",
|
|
3820
|
-
structure: "Pyramid Principle (MECE, SCR)",
|
|
3821
|
-
experts: ["Barbara Minto", "McKinsey", "BCG", "Bain"]
|
|
3822
|
-
},
|
|
3823
|
-
// Investment Banking - Dense, financial, formal
|
|
3824
|
-
investment_banking: {
|
|
3825
|
-
wordsPerSlide: { min: 60, max: 120, ideal: 90 },
|
|
3826
|
-
whitespace: "20-25%",
|
|
3827
|
-
bulletPoints: { max: 8 },
|
|
3828
|
-
fonts: { title: 28, body: 12, minimum: 10 },
|
|
3829
|
-
theme: "mckinsey",
|
|
3830
|
-
structure: "Situation-Complication-Hypothesis",
|
|
3831
|
-
experts: ["Wall Street Prep", "Analyst Academy"]
|
|
3832
|
-
},
|
|
3833
|
-
// Investor Pitch - Concise, startup-friendly
|
|
3834
|
-
investor_pitch: {
|
|
3835
|
-
wordsPerSlide: { min: 5, max: 30, ideal: 15 },
|
|
3836
|
-
whitespace: "35%+",
|
|
3837
|
-
bulletPoints: { max: 4 },
|
|
3838
|
-
fonts: { title: 48, body: 28, minimum: 24 },
|
|
3839
|
-
theme: "startup",
|
|
3840
|
-
structure: "Problem \u2192 Solution \u2192 Market \u2192 Traction \u2192 Team \u2192 Ask",
|
|
3841
|
-
experts: ["Sequoia", "Y Combinator", "DocSend"]
|
|
3842
|
-
},
|
|
3843
|
-
// Technical Presentation - Clear diagrams, code-friendly
|
|
3844
|
-
technical_presentation: {
|
|
3845
|
-
wordsPerSlide: { min: 40, max: 100, ideal: 75 },
|
|
3846
|
-
whitespace: "25%+",
|
|
3847
|
-
bulletPoints: { max: 6 },
|
|
3848
|
-
fonts: { title: 44, body: 20, minimum: 14 },
|
|
3849
|
-
theme: "dark",
|
|
3850
|
-
structure: "TL;DR \u2192 Problem \u2192 Architecture \u2192 Tradeoffs \u2192 Next Steps",
|
|
3851
|
-
experts: ["Edward Tufte", "C4 Model", "Google Design Docs"]
|
|
3852
|
-
},
|
|
3853
|
-
// All Hands - Accessible, clear, motivational
|
|
3854
|
-
all_hands: {
|
|
3855
|
-
wordsPerSlide: { min: 15, max: 40, ideal: 25 },
|
|
3856
|
-
whitespace: "30%+",
|
|
3857
|
-
bulletPoints: { max: 5 },
|
|
3858
|
-
fonts: { title: 52, body: 28, minimum: 24 },
|
|
3859
|
-
theme: "minimal",
|
|
3860
|
-
structure: "Updates \u2192 Wins \u2192 Challenges \u2192 What's Next",
|
|
3861
|
-
experts: ["Internal Communications Best Practices"]
|
|
3862
|
-
}
|
|
3839
|
+
var PALETTE_TO_THEME = {
|
|
3840
|
+
dark_executive: "dark",
|
|
3841
|
+
modern_business: "startup",
|
|
3842
|
+
consulting_classic: "mckinsey",
|
|
3843
|
+
executive_professional: "mckinsey",
|
|
3844
|
+
strategy_growth: "minimal"
|
|
3863
3845
|
};
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
}
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
wordLimitStrict: false,
|
|
3883
|
-
// Consulting allows denser slides
|
|
3884
|
-
requireActionTitles: true,
|
|
3885
|
-
// Titles should state the "so what"
|
|
3886
|
-
requireDataSources: true
|
|
3887
|
-
},
|
|
3888
|
-
investment_banking: {
|
|
3889
|
-
glanceTestSeconds: 10,
|
|
3890
|
-
minScore: 95,
|
|
3891
|
-
wordLimitStrict: false,
|
|
3892
|
-
requireActionTitles: true,
|
|
3893
|
-
requireDataSources: true
|
|
3894
|
-
},
|
|
3895
|
-
investor_pitch: {
|
|
3896
|
-
glanceTestSeconds: 3,
|
|
3897
|
-
minScore: 95,
|
|
3898
|
-
wordLimitStrict: true,
|
|
3899
|
-
requireActionTitles: true,
|
|
3900
|
-
requireDataSources: true
|
|
3901
|
-
},
|
|
3902
|
-
technical_presentation: {
|
|
3903
|
-
glanceTestSeconds: 5,
|
|
3904
|
-
minScore: 95,
|
|
3905
|
-
wordLimitStrict: false,
|
|
3906
|
-
requireActionTitles: false,
|
|
3907
|
-
requireDataSources: true
|
|
3908
|
-
},
|
|
3909
|
-
all_hands: {
|
|
3910
|
-
glanceTestSeconds: 3,
|
|
3911
|
-
minScore: 95,
|
|
3912
|
-
wordLimitStrict: true,
|
|
3913
|
-
requireActionTitles: false,
|
|
3914
|
-
requireDataSources: false
|
|
3846
|
+
async function loadDesignSpecsFromKB(kb, type) {
|
|
3847
|
+
const typeConfig = kb.queryRequired(`presentation_types.${type}`);
|
|
3848
|
+
const validationRules = typeConfig.value.validation_rules;
|
|
3849
|
+
const wordsPerSlide = validationRules.words_per_slide;
|
|
3850
|
+
const whitespace = validationRules.whitespace;
|
|
3851
|
+
const bulletsPerSlide = validationRules.bullets_per_slide;
|
|
3852
|
+
const typography = typeConfig.value.typography;
|
|
3853
|
+
const primaryExperts = typeConfig.value.primary_experts;
|
|
3854
|
+
const colorPalette = typeConfig.value.color_palette || "consulting_classic";
|
|
3855
|
+
const theme = PALETTE_TO_THEME[colorPalette] || "mckinsey";
|
|
3856
|
+
const scoringWeights = typeConfig.value.scoring_weights;
|
|
3857
|
+
let structure = "General presentation structure";
|
|
3858
|
+
if (primaryExperts.some((e) => e.includes("Minto") || e.includes("McKinsey"))) {
|
|
3859
|
+
structure = "Pyramid Principle (MECE, SCR)";
|
|
3860
|
+
} else if (primaryExperts.some((e) => e.includes("Duarte"))) {
|
|
3861
|
+
structure = "Sparkline (What Is / What Could Be)";
|
|
3862
|
+
} else if (primaryExperts.some((e) => e.includes("Cialdini"))) {
|
|
3863
|
+
structure = "Persuasion-driven (SPIN, Challenger)";
|
|
3915
3864
|
}
|
|
3916
|
-
|
|
3865
|
+
return {
|
|
3866
|
+
wordsPerSlide,
|
|
3867
|
+
whitespace,
|
|
3868
|
+
bulletPoints: { max: bulletsPerSlide?.max || 5 },
|
|
3869
|
+
fonts: {
|
|
3870
|
+
title: typography?.titles || "44px, Bold",
|
|
3871
|
+
body: typography?.body || "22px",
|
|
3872
|
+
maxFonts: typography?.max_fonts || 2
|
|
3873
|
+
},
|
|
3874
|
+
theme,
|
|
3875
|
+
structure,
|
|
3876
|
+
experts: primaryExperts,
|
|
3877
|
+
actionTitlesRequired: validationRules.action_titles_required || false,
|
|
3878
|
+
sourcesRequired: validationRules.sources_required || false,
|
|
3879
|
+
scoringWeights: scoringWeights || {
|
|
3880
|
+
visual_quality: 30,
|
|
3881
|
+
content_quality: 30,
|
|
3882
|
+
expert_compliance: 30,
|
|
3883
|
+
accessibility: 10
|
|
3884
|
+
}
|
|
3885
|
+
};
|
|
3886
|
+
}
|
|
3887
|
+
function getQualityCriteria(specs, type) {
|
|
3888
|
+
const isKeynote = type === "ted_keynote" || type === "sales_pitch";
|
|
3889
|
+
const isConsulting = type === "consulting_deck" || type === "investment_banking";
|
|
3890
|
+
return {
|
|
3891
|
+
glanceTestSeconds: isKeynote ? 3 : isConsulting ? 5 : 3,
|
|
3892
|
+
minScore: 95,
|
|
3893
|
+
wordLimitStrict: isKeynote,
|
|
3894
|
+
// Keynotes have strict word limits
|
|
3895
|
+
requireActionTitles: specs.actionTitlesRequired,
|
|
3896
|
+
requireDataSources: specs.sourcesRequired
|
|
3897
|
+
};
|
|
3898
|
+
}
|
|
3917
3899
|
var PresentationEngineV2 = class {
|
|
3918
3900
|
options;
|
|
3901
|
+
kb = null;
|
|
3919
3902
|
constructor(options = {}) {
|
|
3920
3903
|
this.options = {
|
|
3921
3904
|
presentationType: options.presentationType || "consulting_deck",
|
|
@@ -3934,19 +3917,26 @@ var PresentationEngineV2 = class {
|
|
|
3934
3917
|
/**
|
|
3935
3918
|
* Generate a world-class presentation from markdown content.
|
|
3936
3919
|
* Follows knowledge base specs and demands 95+ quality score.
|
|
3920
|
+
*
|
|
3921
|
+
* CRITICAL: All specs come from the Knowledge Base YAML at runtime.
|
|
3922
|
+
* No hardcoded fallbacks - if KB is missing data, we fail loudly.
|
|
3937
3923
|
*/
|
|
3938
3924
|
async generate(markdown, title) {
|
|
3939
3925
|
const warnings = [];
|
|
3926
|
+
this.log("Step 0: Loading Knowledge Base...");
|
|
3927
|
+
this.kb = await initKB();
|
|
3928
|
+
this.log(` KB v${this.kb.getVersion()} loaded`);
|
|
3940
3929
|
this.log("Step 1: Detecting presentation type...");
|
|
3941
3930
|
const detectedType = this.detectPresentationType(markdown);
|
|
3942
3931
|
const presentationType = this.options.presentationType || detectedType;
|
|
3943
3932
|
this.log(` Using type: ${presentationType} (detected: ${detectedType})`);
|
|
3944
3933
|
this.log("Step 2: Loading design specs from Knowledge Base...");
|
|
3945
|
-
const designSpecs =
|
|
3946
|
-
const qualityCriteria =
|
|
3934
|
+
const designSpecs = await loadDesignSpecsFromKB(this.kb, presentationType);
|
|
3935
|
+
const qualityCriteria = getQualityCriteria(designSpecs, presentationType);
|
|
3947
3936
|
this.log(` Theme: ${designSpecs.theme}`);
|
|
3948
3937
|
this.log(` Structure: ${designSpecs.structure}`);
|
|
3949
3938
|
this.log(` Words/slide: ${designSpecs.wordsPerSlide.min}-${designSpecs.wordsPerSlide.max}`);
|
|
3939
|
+
this.log(` Experts: ${designSpecs.experts.slice(0, 2).join(", ")}...`);
|
|
3950
3940
|
this.log("Step 3: Generating slides...");
|
|
3951
3941
|
const generator = createSlideGeneratorV2(presentationType);
|
|
3952
3942
|
let slides = generator.generate(markdown, title);
|
|
@@ -4274,7 +4264,6 @@ SUCCESS: Generated ${slides.length} slides scoring ${review.overallScore}/100`);
|
|
|
4274
4264
|
* Assess the flow and narrative structure of the deck.
|
|
4275
4265
|
*/
|
|
4276
4266
|
assessFlow(slides, type) {
|
|
4277
|
-
const specs = KNOWLEDGE_BASE[type];
|
|
4278
4267
|
let score = 100;
|
|
4279
4268
|
const types = slides.map((s) => s.type);
|
|
4280
4269
|
if (types[0] !== "title") score -= 10;
|
|
@@ -4356,7 +4345,7 @@ Output: ${htmlPath}`);
|
|
|
4356
4345
|
}
|
|
4357
4346
|
|
|
4358
4347
|
// src/qa/SlideQualityReviewer.ts
|
|
4359
|
-
var
|
|
4348
|
+
var DEFAULT_ASSESSMENT_WEIGHTS = {
|
|
4360
4349
|
visualImpact: 0.25,
|
|
4361
4350
|
contentClarity: 0.2,
|
|
4362
4351
|
layoutBalance: 0.15,
|
|
@@ -4365,6 +4354,29 @@ var ASSESSMENT_WEIGHTS = {
|
|
|
4365
4354
|
colorHarmony: 0.1,
|
|
4366
4355
|
audienceAppropriate: 0.05
|
|
4367
4356
|
};
|
|
4357
|
+
function computeWeightsFromKB(kbWeights) {
|
|
4358
|
+
const totalKB = kbWeights.visual_quality + kbWeights.content_quality + kbWeights.expert_compliance + kbWeights.accessibility;
|
|
4359
|
+
const vq = kbWeights.visual_quality / totalKB;
|
|
4360
|
+
const cq = kbWeights.content_quality / totalKB;
|
|
4361
|
+
const ec = kbWeights.expert_compliance / totalKB;
|
|
4362
|
+
const ac = kbWeights.accessibility / totalKB;
|
|
4363
|
+
return {
|
|
4364
|
+
visualImpact: vq * 0.6,
|
|
4365
|
+
// 60% of visual_quality
|
|
4366
|
+
colorHarmony: vq * 0.4,
|
|
4367
|
+
// 40% of visual_quality
|
|
4368
|
+
contentClarity: cq * 0.8,
|
|
4369
|
+
// 80% of content_quality
|
|
4370
|
+
audienceAppropriate: cq * 0.2,
|
|
4371
|
+
// 20% of content_quality
|
|
4372
|
+
layoutBalance: ec * 0.5,
|
|
4373
|
+
// 50% of expert_compliance
|
|
4374
|
+
typographyHierarchy: ec * 0.5,
|
|
4375
|
+
// 50% of expert_compliance
|
|
4376
|
+
whitespaceUsage: ac
|
|
4377
|
+
// 100% of accessibility
|
|
4378
|
+
};
|
|
4379
|
+
}
|
|
4368
4380
|
var SlideQualityReviewer = class {
|
|
4369
4381
|
kb;
|
|
4370
4382
|
initialized = false;
|
|
@@ -4373,6 +4385,9 @@ var SlideQualityReviewer = class {
|
|
|
4373
4385
|
whitespaceRules;
|
|
4374
4386
|
bulletLimit;
|
|
4375
4387
|
glanceTestSeconds;
|
|
4388
|
+
// KB-loaded scoring weights (computed from KB per presentation type)
|
|
4389
|
+
assessmentWeights = DEFAULT_ASSESSMENT_WEIGHTS;
|
|
4390
|
+
_loggedWeights = null;
|
|
4376
4391
|
// Expert rules from KB
|
|
4377
4392
|
hasCialdini = false;
|
|
4378
4393
|
hasGestalt = false;
|
|
@@ -4403,7 +4418,7 @@ var SlideQualityReviewer = class {
|
|
|
4403
4418
|
};
|
|
4404
4419
|
let totalScore = 0;
|
|
4405
4420
|
for (const [key, assessment] of Object.entries(assessments)) {
|
|
4406
|
-
const weight =
|
|
4421
|
+
const weight = this.assessmentWeights[key];
|
|
4407
4422
|
totalScore += assessment.score * weight;
|
|
4408
4423
|
}
|
|
4409
4424
|
const score = Math.round(totalScore);
|
|
@@ -4458,6 +4473,18 @@ var SlideQualityReviewer = class {
|
|
|
4458
4473
|
this.wordLimits = wordLimitsResult.value;
|
|
4459
4474
|
const whitespaceResult = this.kb.getWhitespaceRules(type);
|
|
4460
4475
|
this.whitespaceRules = whitespaceResult.value;
|
|
4476
|
+
try {
|
|
4477
|
+
const weightsResult = this.kb.getScoringWeights(type);
|
|
4478
|
+
const kbWeights = weightsResult.value;
|
|
4479
|
+
this.assessmentWeights = computeWeightsFromKB(kbWeights);
|
|
4480
|
+
if (!this._loggedWeights?.has(type)) {
|
|
4481
|
+
console.log(`[QA] Loaded scoring weights for ${type}: visual=${kbWeights.visual_quality}%, content=${kbWeights.content_quality}%, expert=${kbWeights.expert_compliance}%, accessibility=${kbWeights.accessibility}%`);
|
|
4482
|
+
if (!this._loggedWeights) this._loggedWeights = /* @__PURE__ */ new Set();
|
|
4483
|
+
this._loggedWeights.add(type);
|
|
4484
|
+
}
|
|
4485
|
+
} catch {
|
|
4486
|
+
this.assessmentWeights = DEFAULT_ASSESSMENT_WEIGHTS;
|
|
4487
|
+
}
|
|
4461
4488
|
try {
|
|
4462
4489
|
const glanceResult = this.kb.getGlanceTest();
|
|
4463
4490
|
this.glanceTestSeconds = 3;
|
|
@@ -7751,7 +7778,7 @@ if (typeof process !== "undefined" && process.argv[1]?.includes("CodeQualityVali
|
|
|
7751
7778
|
}
|
|
7752
7779
|
|
|
7753
7780
|
// src/index.ts
|
|
7754
|
-
var VERSION = "
|
|
7781
|
+
var VERSION = "4.1.0";
|
|
7755
7782
|
async function generate(options) {
|
|
7756
7783
|
const {
|
|
7757
7784
|
content,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-presentation-master",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.1.0",
|
|
4
4
|
"description": "Generate world-class presentations using expert methodologies from Duarte, Reynolds, Gallo, and Anderson. Enforces rigorous quality standards through real visual validation.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|