@o-lang/olang 1.2.35 → 1.2.37

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.37",
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,170 @@ 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' },
839
-
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);
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
+ ];
869
866
 
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'
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
+ // ✅ NEW: Check if this is a legal context with contextual allowlist
874
+ const isLegalContext =
875
+ this.context.__verified_intent?.scope === 'legal_analysis_only' ||
876
+ inputs.doc_type === 'contract' ||
877
+ inputs.doc_type === 'nda' ||
878
+ inputs.doc_type === 'agreement' ||
879
+ (typeof text === 'string' && /clause|term|agreement|contract|obligation|penalty|damages|breach|party|shall|herein/i.test(text));
880
+
881
+ // ✅ NEW: Check contextual allowlist if in legal context
882
+ if (isLegalContext && this.context.__verified_intent?.contextual_allowlist) {
883
+ const allowlist = this.context.__verified_intent.contextual_allowlist;
884
+ const triggerWord = match ? match[0].toLowerCase() : '';
885
+
886
+ const allowed = allowlist.some(rule => {
887
+ if (triggerWord.includes(rule.trigger.toLowerCase())) {
888
+ // Check if required legal keywords are present
889
+ return rule.requires.some(keyword =>
890
+ text.toLowerCase().includes(keyword.toLowerCase())
891
+ );
892
+ }
893
+ return false;
880
894
  });
881
-
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
- );
895
+
896
+ if (allowed) {
897
+ // AUDIT LOG: Contextual allowlist bypass
898
+ this._createAuditEntry('safety_bypass', {
899
+ type: 'contextual_allowlist',
900
+ trigger: triggerWord,
901
+ legal_context: true,
902
+ matched_keywords: this.context.__verified_intent.contextual_allowlist
903
+ .find(r => triggerWord.includes(r.trigger.toLowerCase()))?.requires || [],
904
+ severity: 'info'
905
+ });
906
+ continue; // Skip blocking this match
907
+ }
891
908
  }
909
+
910
+ // ✅ AUDIT LOG: Input Safety Violation (only if not bypassed)
911
+ this._createAuditEntry('input_safety_violation', {
912
+ type: 'blocked_input',
913
+ field: field,
914
+ detected_phrase: match ? match[0].trim() : 'unknown pattern',
915
+ capability: capability,
916
+ language: lang,
917
+ african_language_detected: isAfrican,
918
+ financial_expression_found: isFinancial,
919
+ legal_context_detected: isLegalContext,
920
+ severity: 'high'
921
+ });
922
+
923
+ throw new Error(
924
+ `[O-Lang SAFETY] Blocked Input in "${lang}":\n` +
925
+ ` → Detected: "${match ? match[0].trim() : 'Pattern Match'}"\n` +
926
+ ` → Capability: ${capability}\n` +
927
+ ` → Field: ${field}\n` +
928
+ ` → African Language Detected: ${isAfrican}\n` +
929
+ ` → Financial Expression: ${isFinancial}\n` +
930
+ ` → Legal Context: ${isLegalContext}\n` +
931
+ `\n🛑 Workflow halted before execution.`
932
+ );
892
933
  }
893
934
  }
894
- return { passed: true };
895
935
  }
936
+ return { passed: true };
937
+ }
896
938
 
897
939
  // -----------------------------
898
940
  // ✅ KERNEL-LEVEL LLM HALLUCINATION PREVENTION (CONJUGATION-AWARE + EVASION-RESISTANT)