@o-lang/olang 1.2.35 → 1.2.38

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@o-lang/olang",
3
- "version": "1.2.35",
3
+ "version": "1.2.38",
4
4
  "author": "Olalekan Ogundipe <info@olang.cloud>",
5
5
  "description": "O-Lang: A governance language for user-directed, rule-enforced agent workflows",
6
6
  "main": "./src/runtime/index.js",
@@ -462,6 +462,22 @@ if (returnMatch) {
462
462
 
463
463
  flushCurrentStep(); // ✅ Final flush
464
464
 
465
+ // ✅ FALLBACK: Scan raw lines for Return if regex missed it (Windows line endings, hidden chars, etc.)
466
+ if (workflow.returnValues.length === 0) {
467
+ for (let j = 0; j < lines.length; j++) {
468
+ const clean = lines[j].replace(/\r/g, '').trim();
469
+ const match = clean.match(/^Return\s+(.+)$/i);
470
+ if (match) {
471
+ console.log(`[PARSER] Recovered Return at line ${j+1}: "${clean}"`);
472
+ workflow.returnValues = match[1]
473
+ .split(',')
474
+ .map(r => r.trim())
475
+ .filter(r => r !== '');
476
+ break;
477
+ }
478
+ }
479
+ }
480
+
465
481
  // Post-process Save as in actionRaw - ✅ Apply normalization
466
482
  workflow.steps.forEach(step => {
467
483
  if (step.actionRaw && step.saveAs === null) {
@@ -771,128 +771,186 @@ class RuntimeAPI {
771
771
  // -----------------------------
772
772
  // ✅ KERNEL-LEVEL INPUT VALIDATION (Pre-Flight Safety)
773
773
  // -----------------------------
774
- _validateInputs(inputs) {
775
- // Only scan specific input fields that contain user text
776
- const fieldsToScan = ['user_message', 'user_question', 'text', 'prompt'];
777
-
778
- for (const field of fieldsToScan) {
779
- const text = inputs[field];
780
- if (!text || typeof text !== 'string') continue;
781
-
782
- // 🔒 CONJUGATION-AWARE + EVASION-RESISTANT PAN-AFRICAN INTENT DETECTION (INPUT)
783
- const forbiddenPatterns = [
784
- // ────────────────────────────────────────────────
785
- // 🇳🇬 NIGERIAN LANGUAGES (Fixed Unicode Boundaries)
786
- // ────────────────────────────────────────────────
787
-
788
- // YORUBA: Removed trailing \b after 'ṣẹ' to fix Unicode matching
789
- { pattern: /fi\s+(?:owo|ẹ̀wọ̀|ewo|ku|fun|s'ọkọọ)/i, capability: 'transfer', lang: 'yo' },
790
- { pattern: /ranṣẹ\s+(?:owo|pesa|kuɗi|ego)/i, capability: 'transfer', lang: 'yo' },
791
- { pattern: /fi\s+\w+\s+\w+\s+ranṣẹ/i, capability: 'transfer', lang: 'yo' }, // Catches "Fi 5000 naira ranṣẹ"
792
- { pattern: /san\s+(?:owo|ẹ̀wọ̀|ewo|fun|wo)/i, capability: 'payment', lang: 'yo' },
793
- { pattern: /gba\s+owo/i, capability: 'withdrawal', lang: 'yo' },
794
- { pattern: /\bti\s+(?:fi|san|gba|da|lo)/i, capability: 'unauthorized_action', lang: 'yo' },
795
- { pattern: /\b(?:ń|ǹ|n)\s+(?:fi|san|gba)/i, capability: 'unauthorized_action', lang: 'yo' },
796
- { pattern: /\b(mo\s+ti\s+(?:fi|san|gba))/i, capability: 'unauthorized_action', lang: 'yo' },
797
-
798
- // HAUSA: FIXED - Aggressive Substring Match (No Boundaries)
799
- { pattern: /aika.{0,30}ku(?:ɗ|d)i/iu, capability: 'transfer', lang: 'ha' },
800
- { pattern: /ciyar\s*(?:da)?/i, capability: 'transfer', lang: 'ha' },
801
- { pattern: /shiga\s+ku(?:ɗ|d)i/iu, capability: 'transfer', lang: 'ha' },
802
- { pattern: /turo\s+.*\s+aika/i, capability: 'transfer', lang: 'ha' },
803
- { pattern: /biya\s*(?:da)?/i, capability: 'payment', lang: 'ha' },
804
- { pattern: /sahaw[ae]\s+ku(?:ɗ|d)i/iu, capability: 'withdrawal', lang: 'ha' },
805
- { pattern: /(?:ya|ta|su)\s+(?:ciyar|biya|sahawa|sake)/i, capability: 'unauthorized_action', lang: 'ha' },
806
- { pattern: /(?:za\s+a|za\s+ta)\s+(?:ciyar|biya)/i, capability: 'unauthorized_action', lang: 'ha' },
807
- { pattern: /ina\s+(?:ciyar|biya|sahawa)/i, capability: 'unauthorized_action', lang: 'ha' },
808
-
809
-
810
- // IGBO: Removed trailing \b after 'igo'
811
- { pattern: /zipu\s+(?:ego|moni|isi|na)/i, capability: 'transfer', lang: 'ig' },
812
- { pattern: /buru\s+(?:ego|moni|isi)/i, capability: 'transfer', lang: 'ig' },
813
- { pattern: /zi\s+.*\s+zipu/i, capability: 'transfer', lang: 'ig' },
814
- { pattern: /tinye\s+(?:ego|moni|isi)/i, capability: 'deposit', lang: 'ig' },
815
- { pattern: /(?:ziri|bururu|tinyere|gbara)/i, capability: 'unauthorized_action', lang: 'ig' },
816
- { pattern: /m\s+(?:ziri|buru|zipuru|tinyere)/i, capability: 'unauthorized_action', lang: 'ig' },
817
-
818
- // SWAHILI: FIXED - Catch Conjugated Forms (ni-li-pe, a-li-pe)
819
- { pattern: /tuma\s+(?:pesa|fedha)/i, capability: 'transfer', lang: 'sw' },
820
- { pattern: /pelek[ae]?\s+(?:pesa|fedha)/i, capability: 'transfer', lang: 'sw' },
821
- { pattern: /wasilisha/i, capability: 'transfer', lang: 'sw' },
822
- { pattern: /\b\w*lip[ae]\w*/i, capability: 'payment', lang: 'sw' },
823
- { pattern: /maliza\s+malipo/i, capability: 'payment', lang: 'sw' },
824
- { pattern: /ongez[ae]?\s*(?:kiasi|pesa|fedha)/i, capability: 'deposit', lang: 'sw' },
825
- { pattern: /wek[ae]?\s+(?:katika|ndani)\s+(?:akaunti|hisa)/i, capability: 'deposit', lang: 'sw' },
826
- { pattern: /nime(?:tuma|lipa|ongeza|weka|peleka)/i, capability: 'unauthorized_action', lang: 'sw' },
827
-
828
-
829
- // OTHER AFRICAN: FIXED - Direct Unicode Substring
830
- // Amharic: Match roots anywhere
831
- { pattern: /\u120b\u12ad/u, capability: 'transfer', lang: 'am' },
832
- { pattern: /\u1308\u1263/u, capability: 'deposit', lang: 'am' },
833
- { pattern: /\u12ad\u134c\u120d/u, capability: 'payment', lang: 'am' },
834
- { pattern: /[\u1200-\u137F]{0,4}(?:\u1270\u120b\u120b\u1348|\u120b\u12ad|\u12ad\u134c\u120d|\u1338\u121d\u122d|\u12c8\u1323|\u1308\u1263)[\u1200-\u137F]{0,2}/u, capability: 'financial_action', lang: 'am' },
835
-
836
- // Somali
837
- { pattern: /dir\s+(?:lacag|maal|qarsoon)/i, capability: 'transfer', lang: 'so' },
838
- { pattern: /bixi|bixis\s*o/i, capability: 'payment', lang: 'so' },
774
+ // -----------------------------
775
+ // KERNEL-LEVEL INPUT VALIDATION (Pre-Flight Safety) - ENHANCED WITH CONTEXTUAL ALLOWLIST
776
+ // -----------------------------
777
+ _validateInputs(inputs) {
778
+ // Only scan specific input fields that contain user text
779
+ const fieldsToScan = ['user_message', 'user_question', 'text', 'prompt', 'document_text'];
780
+
781
+ for (const field of fieldsToScan) {
782
+ const text = inputs[field];
783
+ if (!text || typeof text !== 'string') continue;
784
+
785
+ // 🔒 CONJUGATION-AWARE + EVASION-RESISTANT PAN-AFRICAN INTENT DETECTION (INPUT)
786
+ const forbiddenPatterns = [
787
+ // ────────────────────────────────────────────────
788
+ // 🇳🇬 NIGERIAN LANGUAGES (Fixed Unicode Boundaries)
789
+ // ────────────────────────────────────────────────
790
+
791
+ // YORUBA: Removed trailing \b after 'ṣẹ' to fix Unicode matching
792
+ { pattern: /fi\s+(?:owo|ẹ̀wọ̀|ewo|ku|fun|s'ọkọọ)/i, capability: 'transfer', lang: 'yo' },
793
+ { pattern: /ranṣẹ\s+(?:owo|pesa|kuɗi|ego)/i, capability: 'transfer', lang: 'yo' },
794
+ { pattern: /fi\s+\w+\s+\w+\s+ranṣẹ/i, capability: 'transfer', lang: 'yo' }, // Catches "Fi 5000 naira ranṣẹ"
795
+ { pattern: /san\s+(?:owo|ẹ̀wọ̀|ewo|fun|wo)/i, capability: 'payment', lang: 'yo' },
796
+ { pattern: /gba\s+owo/i, capability: 'withdrawal', lang: 'yo' },
797
+ { pattern: /\bti\s+(?:fi|san|gba|da|lo)/i, capability: 'unauthorized_action', lang: 'yo' },
798
+ { pattern: /\b(?:ń|ǹ|n)\s+(?:fi|san|gba)/i, capability: 'unauthorized_action', lang: 'yo' },
799
+ { pattern: /\b(mo\s+ti\s+(?:fi|san|gba))/i, capability: 'unauthorized_action', lang: 'yo' },
800
+
801
+ // HAUSA: FIXED - Aggressive Substring Match (No Boundaries)
802
+ { pattern: /aika.{0,30}ku(?:ɗ|d)i/iu, capability: 'transfer', lang: 'ha' },
803
+ { pattern: /ciyar\s*(?:da)?/i, capability: 'transfer', lang: 'ha' },
804
+ { pattern: /shiga\s+ku(?:ɗ|d)i/iu, capability: 'transfer', lang: 'ha' },
805
+ { pattern: /turo\s+.*\s+aika/i, capability: 'transfer', lang: 'ha' },
806
+ { pattern: /biya\s*(?:da)?/i, capability: 'payment', lang: 'ha' },
807
+ { pattern: /sahaw[ae]\s+ku(?:ɗ|d)i/iu, capability: 'withdrawal', lang: 'ha' },
808
+ { pattern: /(?:ya|ta|su)\s+(?:ciyar|biya|sahawa|sake)/i, capability: 'unauthorized_action', lang: 'ha' },
809
+ { pattern: /(?:za\s+a|za\s+ta)\s+(?:ciyar|biya)/i, capability: 'unauthorized_action', lang: 'ha' },
810
+ { pattern: /ina\s+(?:ciyar|biya|sahawa)/i, capability: 'unauthorized_action', lang: 'ha' },
811
+
812
+
813
+ // IGBO: Removed trailing \b after 'igo'
814
+ { pattern: /zipu\s+(?:ego|moni|isi|na)/i, capability: 'transfer', lang: 'ig' },
815
+ { pattern: /buru\s+(?:ego|moni|isi)/i, capability: 'transfer', lang: 'ig' },
816
+ { pattern: /zi\s+.*\s+zipu/i, capability: 'transfer', lang: 'ig' },
817
+ { pattern: /tinye\s+(?:ego|moni|isi)/i, capability: 'deposit', lang: 'ig' },
818
+ { pattern: /(?:ziri|bururu|tinyere|gbara)/i, capability: 'unauthorized_action', lang: 'ig' },
819
+ { pattern: /m\s+(?:ziri|buru|zipuru|tinyere)/i, capability: 'unauthorized_action', lang: 'ig' },
820
+
821
+ // SWAHILI: FIXED - Catch Conjugated Forms (ni-li-pe, a-li-pe)
822
+ { pattern: /tuma\s+(?:pesa|fedha)/i, capability: 'transfer', lang: 'sw' },
823
+ { pattern: /pelek[ae]?\s+(?:pesa|fedha)/i, capability: 'transfer', lang: 'sw' },
824
+ { pattern: /wasilisha/i, capability: 'transfer', lang: 'sw' },
825
+ { pattern: /\b\w*lip[ae]\w*/i, capability: 'payment', lang: 'sw' },
826
+ { pattern: /maliza\s+malipo/i, capability: 'payment', lang: 'sw' },
827
+ { pattern: /ongez[ae]?\s*(?:kiasi|pesa|fedha)/i, capability: 'deposit', lang: 'sw' },
828
+ { pattern: /wek[ae]?\s+(?:katika|ndani)\s+(?:akaunti|hisa)/i, capability: 'deposit', lang: 'sw' },
829
+ { pattern: /nime(?:tuma|lipa|ongeza|weka|peleka)/i, capability: 'unauthorized_action', lang: 'sw' },
830
+
831
+
832
+ // OTHER AFRICAN: FIXED - Direct Unicode Substring
833
+ // Amharic: Match roots anywhere
834
+ { pattern: /\u120b\u12ad/u, capability: 'transfer', lang: 'am' },
835
+ { pattern: /\u1308\u1263/u, capability: 'deposit', lang: 'am' },
836
+ { pattern: /\u12ad\u134c\u120d/u, capability: 'payment', lang: 'am' },
837
+ { pattern: /[\u1200-\u137F]{0,4}(?:\u1270\u120b\u120b\u1348|\u120b\u12ad|\u12ad\u134c\u120d|\u1338\u121d\u122d|\u12c8\u1323|\u1308\u1263)[\u1200-\u137F]{0,2}/u, capability: 'financial_action', lang: 'am' },
838
+
839
+ // Somali
840
+ { pattern: /dir\s+(?:lacag|maal|qarsoon)/i, capability: 'transfer', lang: 'so' },
841
+ { pattern: /bixi|bixis\s*o/i, capability: 'payment', lang: 'so' },
842
+
843
+ // Zulu: ✅ FIXED - Handle Subject Concords (u-thumela, ngi-hlawule)
844
+ { pattern: /thumel/i, capability: 'transfer', lang: 'zu' }, // Matches root inside uthumela, ngithumela
845
+ { pattern: /thumel.*imali/i, capability: 'transfer', lang: 'zu' },
846
+ { pattern: /hlawul/i, capability: 'payment', lang: 'zu' }, // Matches root inside hlawula, ngihlawule
847
+ { pattern: /hlawul.*imali/i, capability: 'payment', lang: 'zu' },
848
+
849
+ // ────────────────────────────────────────────────
850
+ // 🌐 GLOBAL LANGUAGES
851
+ // ────────────────────────────────────────────────
852
+ { pattern: /\b(transfer(?:red|ring)?|send(?:t|ing)?|wire(?:d)?|pay(?:ed|ing)?|withdraw(?:n)?|deposit(?:ed|ing)?)\b/i, capability: 'financial_action', lang: 'en' },
853
+ { pattern: /\bI\s+(?:can|will|am able to|have|'ve|did|already)\s+(?:transfer|send|pay|withdraw|deposit|wire)\b/i, capability: 'unauthorized_action', lang: 'en' },
854
+ { pattern: /\b(virer|transférer|envoyer|payer|retirer|déposer)\b/i, capability: 'financial_action', lang: 'fr' },
855
+ { pattern: /[\u0600-\u06FF]{0,3}(?:حوّل|أرسل|ادفع|اودع|سحب)[\u0600-\u06FF]{0,3}/u, capability: 'financial_action', lang: 'ar' },
856
+ { pattern: /[\u4e00-\u9fff]{0,2}(?:转账 | 支付 | 存款 | 取款)[\u4e00-\u9fff]{0,2}/u, capability: 'financial_action', lang: 'zh' },
857
+
858
+ // ────────────────────────────────────────────────
859
+ // 🛡️ PII & EVASION
860
+ // ────────────────────────────────────────────────
861
+ { pattern: /\b(?:\+?234\s*|0)(?:70|80|81|90|91)\d{8}\b/, capability: 'pii_exposure', lang: 'multi' },
862
+ { pattern: /\b(?:bvn|bank\s+verification\s+number)\b.{0,20}\d{11}/i, capability: 'pii_exposure', lang: 'multi' },
863
+ { pattern: /(?:account|acct|a\/c|akaunti|asusu|hesabu|namba|#)\s*[:\-—–]?\s*(\d{6,})/i, capability: 'pii_exposure', lang: 'multi' },
864
+ { pattern: /\b(successful(?:ly)?|confirmed|approved|completed|processed|verified|imethibitishwa|imefanikiwa)\b/i, capability: 'deceptive_claim', lang: 'multi' },
865
+ ];
866
+
867
+ for (const { pattern, capability, lang } of forbiddenPatterns) {
868
+ if (pattern.test(text)) {
869
+ const match = text.match(pattern);
870
+ const isAfrican = ['yo', 'ig', 'ha', 'sw', 'zu', 'am', 'om', 'ff', 'so', 'sn'].includes(lang);
871
+ const isFinancial = ['transfer', 'payment', 'withdrawal', 'deposit', 'financial_action'].includes(capability);
872
+
873
+ // ✅ DECOUPLED: Check legal context via standardized signals (not UI fields)
874
+ const intent = this.context.__verified_intent || {};
875
+ const signals = intent.context_signals || {};
876
+
877
+ const isLegalContext =
878
+ // Signal 1: Explicit scope declaration
879
+ intent.scope === 'legal_analysis_only' ||
880
+
881
+ // Signal 2: Standardized context signals (server-mapped, UI-agnostic)
882
+ signals.isLegalDocument === true ||
883
+ signals.documentCategory === 'contract' ||
884
+ signals.documentCategory === 'nda' ||
885
+ signals.documentCategory === 'agreement' ||
886
+ signals.documentCategory === 'legal' ||
887
+
888
+ // Signal 3: Semantic fallback (works even if signals missing)
889
+ (typeof text === 'string' && /clause|term|agreement|contract|obligation|penalty|damages|breach|party|shall|herein/i.test(text));
839
890
 
840
- // Zulu: FIXED - Handle Subject Concords (u-thumela, ngi-hlawule)
841
- { pattern: /thumel/i, capability: 'transfer', lang: 'zu' }, // Matches root inside uthumela, ngithumela
842
- { pattern: /thumel.*imali/i, capability: 'transfer', lang: 'zu' },
843
- { pattern: /hlawul/i, capability: 'payment', lang: 'zu' }, // Matches root inside hlawula, ngihlawule
844
- { pattern: /hlawul.*imali/i, capability: 'payment', lang: 'zu' },
845
-
846
- // ────────────────────────────────────────────────
847
- // 🌐 GLOBAL LANGUAGES
848
- // ────────────────────────────────────────────────
849
- { pattern: /\b(transfer(?:red|ring)?|send(?:t|ing)?|wire(?:d)?|pay(?:ed|ing)?|withdraw(?:n)?|deposit(?:ed|ing)?)\b/i, capability: 'financial_action', lang: 'en' },
850
- { pattern: /\bI\s+(?:can|will|am able to|have|'ve|did|already)\s+(?:transfer|send|pay|withdraw|deposit|wire)\b/i, capability: 'unauthorized_action', lang: 'en' },
851
- { pattern: /\b(virer|transférer|envoyer|payer|retirer|déposer)\b/i, capability: 'financial_action', lang: 'fr' },
852
- { pattern: /[\u0600-\u06FF]{0,3}(?:حوّل|أرسل|ادفع|اودع|سحب)[\u0600-\u06FF]{0,3}/u, capability: 'financial_action', lang: 'ar' },
853
- { pattern: /[\u4e00-\u9fff]{0,2}(?:转账 | 支付 | 存款 | 取款)[\u4e00-\u9fff]{0,2}/u, capability: 'financial_action', lang: 'zh' },
854
-
855
- // ────────────────────────────────────────────────
856
- // 🛡️ PII & EVASION
857
- // ────────────────────────────────────────────────
858
- { pattern: /\b(?:\+?234\s*|0)(?:70|80|81|90|91)\d{8}\b/, capability: 'pii_exposure', lang: 'multi' },
859
- { pattern: /\b(?:bvn|bank\s+verification\s+number)\b.{0,20}\d{11}/i, capability: 'pii_exposure', lang: 'multi' },
860
- { pattern: /(?:account|acct|a\/c|akaunti|asusu|hesabu|namba|#)\s*[:\-—–]?\s*(\d{6,})/i, capability: 'pii_exposure', lang: 'multi' },
861
- { pattern: /\b(successful(?:ly)?|confirmed|approved|completed|processed|verified|imethibitishwa|imefanikiwa)\b/i, capability: 'deceptive_claim', lang: 'multi' },
862
- ];
863
-
864
- for (const { pattern, capability, lang } of forbiddenPatterns) {
865
- if (pattern.test(text)) {
866
- const match = text.match(pattern);
867
- const isAfrican = ['yo', 'ig', 'ha', 'sw', 'zu', 'am', 'om', 'ff', 'so', 'sn'].includes(lang);
868
- const isFinancial = ['transfer', 'payment', 'withdrawal', 'deposit', 'financial_action'].includes(capability);
891
+ // ✅ NEW: Check contextual allowlist if in legal context
892
+ if (isLegalContext && this.context.__verified_intent?.contextual_allowlist) {
893
+ const allowlist = this.context.__verified_intent.contextual_allowlist;
894
+ const triggerWord = match ? match[0].toLowerCase() : '';
895
+
896
+ // Inside the contextual allowlist check in _validateInputs:
897
+ const allowed = allowlist.some(rule => {
898
+ // Check if this pattern's capability matches the rule's trigger
899
+ const triggerMatch =
900
+ triggerWord.includes(rule.trigger.toLowerCase()) ||
901
+ capability.toLowerCase().includes(rule.trigger.toLowerCase()); // Handle capability-level triggers
902
+
903
+ if (triggerMatch) {
904
+ // Check if required legal keywords are present
905
+ return rule.requires.some(keyword =>
906
+ text.toLowerCase().includes(keyword.toLowerCase())
907
+ );
908
+ }
909
+ return false;
910
+ });
911
+
912
+ if (allowed) {
913
+ // ✅ AUDIT LOG: Contextual allowlist bypass
914
+ this._createAuditEntry('safety_bypass', {
915
+ type: 'contextual_allowlist',
916
+ trigger: triggerWord,
917
+ legal_context: true,
918
+ matched_keywords: this.context.__verified_intent.contextual_allowlist
919
+ .find(r => triggerWord.includes(r.trigger.toLowerCase()))?.requires || [],
920
+ severity: 'info'
921
+ });
922
+ continue; // Skip blocking this match
923
+ }
924
+ }
869
925
 
870
- // ✅ AUDIT LOG: Input Safety Violation
871
- this._createAuditEntry('input_safety_violation', {
872
- type: 'blocked_input',
873
- field: field,
874
- detected_phrase: match ? match[0].trim() : 'unknown pattern',
875
- capability: capability,
876
- language: lang,
877
- african_language_detected: isAfrican,
878
- financial_expression_found: isFinancial,
879
- severity: 'high'
880
- });
926
+ // ✅ AUDIT LOG: Input Safety Violation (only if not bypassed)
927
+ this._createAuditEntry('input_safety_violation', {
928
+ type: 'blocked_input',
929
+ field: field,
930
+ detected_phrase: match ? match[0].trim() : 'unknown pattern',
931
+ capability: capability,
932
+ language: lang,
933
+ african_language_detected: isAfrican,
934
+ financial_expression_found: isFinancial,
935
+ legal_context_detected: isLegalContext,
936
+ severity: 'high'
937
+ });
881
938
 
882
- throw new Error(
883
- `[O-Lang SAFETY] Blocked Input in "${lang}":\n` +
884
- ` → Detected: "${match ? match[0].trim() : 'Pattern Match'}"\n` +
885
- ` → Capability: ${capability}\n` +
886
- ` → Field: ${field}\n` +
887
- ` → African Language Detected: ${isAfrican}\n` +
888
- ` → Financial Expression: ${isFinancial}\n` +
889
- `\n🛑 Workflow halted before execution.`
890
- );
891
- }
939
+ throw new Error(
940
+ `[O-Lang SAFETY] Blocked Input in "${lang}":\n` +
941
+ ` → Detected: "${match ? match[0].trim() : 'Pattern Match'}"\n` +
942
+ ` → Capability: ${capability}\n` +
943
+ ` → Field: ${field}\n` +
944
+ ` → African Language Detected: ${isAfrican}\n` +
945
+ ` → Financial Expression: ${isFinancial}\n` +
946
+ ` → Legal Context: ${isLegalContext}\n` +
947
+ `\n🛑 Workflow halted before execution.`
948
+ );
892
949
  }
893
950
  }
894
- return { passed: true };
895
951
  }
952
+ return { passed: true };
953
+ }
896
954
 
897
955
  // -----------------------------
898
956
  // ✅ KERNEL-LEVEL LLM HALLUCINATION PREVENTION (CONJUGATION-AWARE + EVASION-RESISTANT)