@llm-dev-ops/agentics-cli 2.7.2 → 2.7.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -14,6 +14,7 @@
14
14
  * permitted I/O path and never throws.
15
15
  */
16
16
  import { loadUnitEconomics, buildFinancialModelFromUnitEconomics, enforceManifestConsistency, } from './unit-economics-loader.js';
17
+ import { classifySector } from './domain-unit-registry.js';
17
18
  import { fcvTag, countFcvTags, fcvTagKeys } from './financial-claim-extractor.js';
18
19
  import { recordDegradation } from '../observability/degradations.js';
19
20
  import { classifyLaborIntensity, isLaborIntensive, workforceRiskTemplate, workforceRaciTemplate, workforceSensitivityRow, estimateWorkforceExposure, } from './domain-labor-classifier.js';
@@ -493,63 +494,132 @@ function estimateFinancialsFromQuery(query) {
493
494
  }
494
495
  }
495
496
  }
496
- // Industry detection
497
- const isPharma = lower.includes('pharma') || lower.includes('drug') || lower.includes('gxp');
498
- const isFinancial = lower.includes('financial') || lower.includes('banking') || lower.includes('insurance');
499
- const isRetail = lower.includes('retail') || lower.includes('grocery') || lower.includes('store');
500
- const isUtility = lower.includes('water') || lower.includes('utility') || lower.includes('energy') || lower.includes('grid');
501
- const isHealthcare = lower.includes('healthcare') || lower.includes('hospital') || lower.includes('patient');
502
- const isSustainability = lower.includes('sustainability') || lower.includes('emissions') || lower.includes('carbon') || lower.includes('esg');
503
- const isProfessionalServices = lower.includes('professional services') || lower.includes('consulting') || lower.includes('advisory');
504
- const isManufacturing = lower.includes('manufacturing') || lower.includes('factory') || lower.includes('production line');
505
- const isConsumerGoods = lower.includes('consumer goods') || lower.includes('cpg') || lower.includes('fmcg') || lower.includes('packaging');
497
+ // ADR-PIPELINE-095 — Sector-aware industry detection.
498
+ //
499
+ // Pre-095 this function used keyword `lower.includes()` checks that were
500
+ // checked in the WRONG order: `isFinancial` (matched on "financial
501
+ // operations") fired before `isSustainability`, so an Archibus / workplace-
502
+ // strategy / sustainability brief got costPerEmployee=$30 financial-services
503
+ // defaults that diverged from `unit-economics.json`'s sector-derived numbers.
504
+ //
505
+ // Now: delegate to `classifySector` first (the same classifier that drives
506
+ // unit-economics), so a brief identified as `commercial-real-estate`,
507
+ // `hospitality`, `manufacturing` etc. picks numbers consistent with the
508
+ // financial model. Only when the sector is `unknown` do we fall through to
509
+ // the keyword detector — and that detector now checks `isSustainability`
510
+ // before `isFinancial` so sustainability briefs that mention "financial
511
+ // operations" don't get misrouted.
512
+ const sectorClass = classifySector(query);
506
513
  let industryLabel = 'enterprise';
507
514
  let costPerEmployee = 25;
508
515
  let savingsMultiplier = 50;
509
- if (isPharma) {
510
- costPerEmployee = 35;
511
- savingsMultiplier = 80;
512
- industryLabel = 'pharmaceutical';
513
- }
514
- else if (isFinancial) {
515
- costPerEmployee = 30;
516
- savingsMultiplier = 60;
517
- industryLabel = 'financial services';
518
- }
519
- else if (isRetail) {
520
- costPerEmployee = 15;
521
- savingsMultiplier = 40;
522
- industryLabel = 'retail';
523
- }
524
- else if (isUtility) {
525
- costPerEmployee = 20;
526
- savingsMultiplier = 55;
527
- industryLabel = 'utility infrastructure';
528
- }
529
- else if (isHealthcare) {
530
- costPerEmployee = 30;
531
- savingsMultiplier = 65;
532
- industryLabel = 'healthcare';
533
- }
534
- else if (isManufacturing) {
535
- costPerEmployee = 22;
536
- savingsMultiplier = 55;
537
- industryLabel = 'manufacturing';
538
- }
539
- else if (isConsumerGoods) {
540
- costPerEmployee = 20;
541
- savingsMultiplier = 45;
542
- industryLabel = 'consumer goods';
543
- }
544
- else if (isSustainability) {
545
- costPerEmployee = 25;
546
- savingsMultiplier = 50;
547
- industryLabel = 'sustainability';
548
- }
549
- else if (isProfessionalServices) {
550
- costPerEmployee = 25;
551
- savingsMultiplier = 50;
552
- industryLabel = 'professional services';
516
+ switch (sectorClass) {
517
+ case 'commercial-real-estate':
518
+ costPerEmployee = 30;
519
+ savingsMultiplier = 50;
520
+ industryLabel = 'workplace optimization';
521
+ break;
522
+ case 'hospitality':
523
+ costPerEmployee = 25;
524
+ savingsMultiplier = 50;
525
+ industryLabel = 'hospitality';
526
+ break;
527
+ case 'airline-catering':
528
+ costPerEmployee = 30;
529
+ savingsMultiplier = 60;
530
+ industryLabel = 'airline catering';
531
+ break;
532
+ case 'fleet':
533
+ costPerEmployee = 25;
534
+ savingsMultiplier = 55;
535
+ industryLabel = 'fleet';
536
+ break;
537
+ case 'retail':
538
+ costPerEmployee = 15;
539
+ savingsMultiplier = 40;
540
+ industryLabel = 'retail';
541
+ break;
542
+ case 'manufacturing':
543
+ costPerEmployee = 22;
544
+ savingsMultiplier = 55;
545
+ industryLabel = 'manufacturing';
546
+ break;
547
+ case 'healthcare':
548
+ costPerEmployee = 30;
549
+ savingsMultiplier = 65;
550
+ industryLabel = 'healthcare';
551
+ break;
552
+ case 'data-center':
553
+ costPerEmployee = 30;
554
+ savingsMultiplier = 55;
555
+ industryLabel = 'data center';
556
+ break;
557
+ case 'call-center':
558
+ costPerEmployee = 15;
559
+ savingsMultiplier = 45;
560
+ industryLabel = 'call center';
561
+ break;
562
+ default: {
563
+ // Sector unknown — use keyword detector. Order matters: sustainability,
564
+ // pharma, healthcare, manufacturing, utility BEFORE the broader
565
+ // financial / retail / consumer-goods / professional-services nets so
566
+ // a more-specific signal wins over generic words like "financial".
567
+ const isPharma = lower.includes('pharma') || lower.includes('drug') || lower.includes('gxp');
568
+ const isHealthcare = lower.includes('healthcare') || lower.includes('hospital') || lower.includes('patient');
569
+ const isManufacturing = lower.includes('manufacturing') || lower.includes('factory') || lower.includes('production line');
570
+ const isUtility = lower.includes('water') || lower.includes('utility') || lower.includes('energy') || lower.includes('grid');
571
+ const isSustainability = lower.includes('sustainability') || lower.includes('emissions') || lower.includes('carbon') || lower.includes('esg');
572
+ const isFinancial = lower.includes('financial') || lower.includes('banking') || lower.includes('insurance');
573
+ const isRetail = lower.includes('retail') || lower.includes('grocery') || lower.includes('store');
574
+ const isProfessionalServices = lower.includes('professional services') || lower.includes('consulting') || lower.includes('advisory');
575
+ const isConsumerGoods = lower.includes('consumer goods') || lower.includes('cpg') || lower.includes('fmcg') || lower.includes('packaging');
576
+ if (isPharma) {
577
+ costPerEmployee = 35;
578
+ savingsMultiplier = 80;
579
+ industryLabel = 'pharmaceutical';
580
+ }
581
+ else if (isHealthcare) {
582
+ costPerEmployee = 30;
583
+ savingsMultiplier = 65;
584
+ industryLabel = 'healthcare';
585
+ }
586
+ else if (isManufacturing) {
587
+ costPerEmployee = 22;
588
+ savingsMultiplier = 55;
589
+ industryLabel = 'manufacturing';
590
+ }
591
+ else if (isUtility) {
592
+ costPerEmployee = 20;
593
+ savingsMultiplier = 55;
594
+ industryLabel = 'utility infrastructure';
595
+ }
596
+ else if (isSustainability) {
597
+ costPerEmployee = 25;
598
+ savingsMultiplier = 50;
599
+ industryLabel = 'sustainability';
600
+ }
601
+ else if (isFinancial) {
602
+ costPerEmployee = 30;
603
+ savingsMultiplier = 60;
604
+ industryLabel = 'financial services';
605
+ }
606
+ else if (isRetail) {
607
+ costPerEmployee = 15;
608
+ savingsMultiplier = 40;
609
+ industryLabel = 'retail';
610
+ }
611
+ else if (isConsumerGoods) {
612
+ costPerEmployee = 20;
613
+ savingsMultiplier = 45;
614
+ industryLabel = 'consumer goods';
615
+ }
616
+ else if (isProfessionalServices) {
617
+ costPerEmployee = 25;
618
+ savingsMultiplier = 50;
619
+ industryLabel = 'professional services';
620
+ }
621
+ break;
622
+ }
553
623
  }
554
624
  // Use employees for the per-employee fallback model.
555
625
  // Domain-specific models (packaging, fleet, water, energy, etc.) handle their own unit economics.