mirror of
https://github.com/elder-plinius/P4RS3LT0NGV3.git
synced 2026-07-21 03:21:05 +02:00
Add Latin-root lexeme analysis to prompt tools
This commit is contained in:
@@ -0,0 +1,180 @@
|
||||
/**
|
||||
* Shared Latin-root lexeme analysis and neutral rewrite generation.
|
||||
*/
|
||||
(function(root) {
|
||||
function uniq(values) {
|
||||
return Array.from(new Set(values.filter(Boolean)));
|
||||
}
|
||||
|
||||
function titleCase(text) {
|
||||
return String(text || '').replace(/\b[a-z]/g, function(match) {
|
||||
return match.toUpperCase();
|
||||
});
|
||||
}
|
||||
|
||||
function preserveCase(source, replacement) {
|
||||
if (!source) {
|
||||
return replacement;
|
||||
}
|
||||
if (source === source.toUpperCase()) {
|
||||
return replacement.toUpperCase();
|
||||
}
|
||||
if (source[0] === source[0].toUpperCase() && source.slice(1) === source.slice(1).toLowerCase()) {
|
||||
return titleCase(replacement);
|
||||
}
|
||||
return replacement;
|
||||
}
|
||||
|
||||
function normalizeRoot(rawRoot, aliases) {
|
||||
const rootText = String(rawRoot || '').toLowerCase();
|
||||
if (!rootText) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (aliases[rootText]) {
|
||||
return aliases[rootText];
|
||||
}
|
||||
|
||||
const variants = [
|
||||
rootText.endsWith('i') ? rootText.slice(0, -1) : '',
|
||||
rootText.endsWith('ic') ? rootText.slice(0, -2) : '',
|
||||
rootText.endsWith('o') ? rootText.slice(0, -1) : '',
|
||||
rootText.endsWith('al') ? rootText.slice(0, -2) : ''
|
||||
].filter(Boolean);
|
||||
|
||||
for (const variant of variants) {
|
||||
if (aliases[variant]) {
|
||||
return aliases[variant];
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
function materializeTemplates(templates, domain) {
|
||||
return uniq((templates || []).map(function(template) {
|
||||
return String(template || '').replace(/\{domain\}/g, domain || 'risk');
|
||||
}));
|
||||
}
|
||||
|
||||
function resolveSuggestions(policy, domain) {
|
||||
if (domain) {
|
||||
return materializeTemplates(policy.rewriteTemplates, domain);
|
||||
}
|
||||
return uniq(policy.fallbackTemplates || []);
|
||||
}
|
||||
|
||||
function analyze(text, options) {
|
||||
const input = String(text || '');
|
||||
const policies = (options && options.policies) || root.LATIN_AFFIX_POLICIES || [];
|
||||
const aliases = (options && options.aliases) || root.LATIN_DOMAIN_ALIASES || {};
|
||||
|
||||
if (!input.trim()) {
|
||||
return {
|
||||
sourceText: input,
|
||||
totalFindings: 0,
|
||||
findings: [],
|
||||
families: [],
|
||||
summary: 'No Latin-root wording findings.'
|
||||
};
|
||||
}
|
||||
|
||||
const findings = [];
|
||||
const seen = new Set();
|
||||
|
||||
policies.forEach(function(policy) {
|
||||
(policy.patterns || []).forEach(function(pattern) {
|
||||
let match;
|
||||
while ((match = pattern.exec(input)) !== null) {
|
||||
const term = match[0];
|
||||
const key = policy.id + '::' + term.toLowerCase();
|
||||
if (seen.has(key)) {
|
||||
continue;
|
||||
}
|
||||
seen.add(key);
|
||||
|
||||
const rootCandidate = match[1] || '';
|
||||
const semanticDomain = normalizeRoot(rootCandidate, aliases);
|
||||
const rewrites = resolveSuggestions(policy, semanticDomain);
|
||||
|
||||
findings.push({
|
||||
id: key,
|
||||
term,
|
||||
normalizedTerm: term.toLowerCase(),
|
||||
family: policy.family,
|
||||
policyId: policy.id,
|
||||
affixes: policy.affixes || [],
|
||||
partOfSpeech: policy.partOfSpeech,
|
||||
extractedRoot: rootCandidate || '',
|
||||
semanticDomain: semanticDomain || '',
|
||||
severity: policy.severity,
|
||||
confidence: policy.confidence,
|
||||
semanticShift: policy.semanticShift,
|
||||
rationale: policy.explanation,
|
||||
rewrites,
|
||||
primaryRewrite: rewrites[0] || '',
|
||||
matchIndex: match.index
|
||||
});
|
||||
}
|
||||
pattern.lastIndex = 0;
|
||||
});
|
||||
});
|
||||
|
||||
findings.sort(function(a, b) {
|
||||
return a.matchIndex - b.matchIndex;
|
||||
});
|
||||
|
||||
return {
|
||||
sourceText: input,
|
||||
totalFindings: findings.length,
|
||||
findings,
|
||||
families: uniq(findings.map(function(item) { return item.family; })),
|
||||
summary: findings.length
|
||||
? 'Detected ' + findings.length + ' Latin-root wording pattern' + (findings.length === 1 ? '' : 's') + '.'
|
||||
: 'No Latin-root wording findings.'
|
||||
};
|
||||
}
|
||||
|
||||
function neutralizeText(text, analysis) {
|
||||
const input = String(text || '');
|
||||
if (!analysis || !Array.isArray(analysis.findings) || !analysis.findings.length) {
|
||||
return input;
|
||||
}
|
||||
|
||||
let output = input;
|
||||
analysis.findings.forEach(function(finding) {
|
||||
if (!finding.primaryRewrite) {
|
||||
return;
|
||||
}
|
||||
const matcher = new RegExp('\\b' + escapeRegExp(finding.term) + '\\b', 'gi');
|
||||
output = output.replace(matcher, function(match) {
|
||||
return preserveCase(match, finding.primaryRewrite);
|
||||
});
|
||||
});
|
||||
return output;
|
||||
}
|
||||
|
||||
function escapeRegExp(value) {
|
||||
return String(value || '').replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
}
|
||||
|
||||
const api = {
|
||||
analyze,
|
||||
neutralizeText
|
||||
};
|
||||
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
const data = require('../data/latinAffixPolicies.js');
|
||||
module.exports = {
|
||||
analyze: function(text) {
|
||||
return analyze(text, {
|
||||
policies: data.POLICIES,
|
||||
aliases: data.DOMAIN_ALIASES
|
||||
});
|
||||
},
|
||||
neutralizeText
|
||||
};
|
||||
} else {
|
||||
root.LexemeAnalysis = api;
|
||||
}
|
||||
})(typeof window !== 'undefined' ? window : globalThis);
|
||||
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* Declarative Latin-root prompt wording policies.
|
||||
* Families define how loaded affixes should be interpreted and rewritten.
|
||||
*/
|
||||
(function(root) {
|
||||
const DOMAIN_ALIASES = {
|
||||
bacter: 'bacterial',
|
||||
bacteri: 'bacterial',
|
||||
bio: 'biological',
|
||||
bi: 'biological',
|
||||
fung: 'fungal',
|
||||
fungi: 'fungal',
|
||||
germ: 'microbial',
|
||||
herb: 'weed',
|
||||
homic: 'violence',
|
||||
human: 'human',
|
||||
insect: 'pest',
|
||||
larv: 'larval',
|
||||
pestic: 'pest',
|
||||
pesti: 'pest',
|
||||
rodent: 'rodent',
|
||||
suic: 'self-harm',
|
||||
viru: 'viral',
|
||||
virus: 'viral'
|
||||
};
|
||||
|
||||
const POLICIES = [
|
||||
{
|
||||
id: 'latin-destructive-noun',
|
||||
family: 'destructive_suffix',
|
||||
kind: 'suffix',
|
||||
partOfSpeech: 'noun',
|
||||
affixes: ['cide'],
|
||||
patterns: [/\b([a-z]+?)cide(s)?\b/gi],
|
||||
severity: 'high',
|
||||
confidence: 0.91,
|
||||
semanticShift: 'lethal_or_destructive',
|
||||
explanation: 'The Latin-derived -cide ending tends to foreground killing or eradication.',
|
||||
rewriteTemplates: [
|
||||
'{domain} management',
|
||||
'{domain} mitigation',
|
||||
'{domain} control',
|
||||
'{domain} stewardship'
|
||||
],
|
||||
fallbackTemplates: [
|
||||
'mitigation',
|
||||
'management',
|
||||
'deterrence',
|
||||
'stewardship'
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'latin-destructive-adjective',
|
||||
family: 'destructive_suffix',
|
||||
kind: 'suffix',
|
||||
partOfSpeech: 'adjective',
|
||||
affixes: ['cidal'],
|
||||
patterns: [/\b([a-z]+?)cidal(ly)?\b/gi, /\bcidal(ly)?\b/gi],
|
||||
severity: 'medium',
|
||||
confidence: 0.84,
|
||||
semanticShift: 'destructive_operational_framing',
|
||||
explanation: 'The Latin-derived -cidal ending can make otherwise neutral activity sound destructive.',
|
||||
rewriteTemplates: [
|
||||
'focused on {domain} management',
|
||||
'used for {domain} mitigation',
|
||||
'intended for {domain} control'
|
||||
],
|
||||
fallbackTemplates: [
|
||||
'framed around mitigation',
|
||||
'framed around management',
|
||||
'operationally neutral'
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
const api = {
|
||||
DOMAIN_ALIASES,
|
||||
POLICIES
|
||||
};
|
||||
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
module.exports = api;
|
||||
} else {
|
||||
root.LATIN_AFFIX_POLICIES = POLICIES;
|
||||
root.LATIN_DOMAIN_ALIASES = DOMAIN_ALIASES;
|
||||
}
|
||||
})(typeof window !== 'undefined' ? window : globalThis);
|
||||
@@ -24,6 +24,7 @@ class AntiClassifierTool extends Tool {
|
||||
acInput: '',
|
||||
acOutput: '',
|
||||
acError: '',
|
||||
acLexemeAnalysis: { totalFindings: 0, findings: [], summary: 'No Latin-root wording findings.' },
|
||||
acLoading: false,
|
||||
acModel: localStorage.getItem('ac-model') || 'anthropic/claude-sonnet-4.6',
|
||||
acModels: models,
|
||||
@@ -49,6 +50,13 @@ class AntiClassifierTool extends Tool {
|
||||
? window.ANTICLASSIFIER_SYSTEM_PROMPT
|
||||
: '';
|
||||
},
|
||||
acRefreshLexemeAnalysis: function() {
|
||||
if (typeof window === 'undefined' || !window.LexemeAnalysis || typeof window.LexemeAnalysis.analyze !== 'function') {
|
||||
this.acLexemeAnalysis = { totalFindings: 0, findings: [], summary: 'Lexeme analysis unavailable.' };
|
||||
return;
|
||||
}
|
||||
this.acLexemeAnalysis = window.LexemeAnalysis.analyze(this.acInput);
|
||||
},
|
||||
acRun: async function() {
|
||||
const apiKey = this.acGetApiKey();
|
||||
if (!apiKey) {
|
||||
@@ -123,6 +131,39 @@ class AntiClassifierTool extends Tool {
|
||||
if (this.acOutput) {
|
||||
this.copyToClipboard(this.acOutput);
|
||||
}
|
||||
},
|
||||
acGetLexemeAnalysis: function() {
|
||||
return this.acLexemeAnalysis || { totalFindings: 0, findings: [], summary: 'No Latin-root wording findings.' };
|
||||
},
|
||||
acNeutralizeInput: function() {
|
||||
const analysis = this.acGetLexemeAnalysis();
|
||||
if (!analysis.totalFindings || !window.LexemeAnalysis || typeof window.LexemeAnalysis.neutralizeText !== 'function') {
|
||||
return;
|
||||
}
|
||||
this.acInput = window.LexemeAnalysis.neutralizeText(this.acInput, analysis);
|
||||
if (typeof this.showNotification === 'function') {
|
||||
this.showNotification('Applied neutral Latin-root rewrites', 'success', 'fas fa-seedling');
|
||||
}
|
||||
},
|
||||
acApplyLexemeRewrite: function(term, rewrite) {
|
||||
if (!term || !rewrite) {
|
||||
return;
|
||||
}
|
||||
const escapedTerm = String(term).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
this.acInput = this.acInput.replace(new RegExp('\\b' + escapedTerm + '\\b', 'i'), rewrite);
|
||||
if (typeof this.showNotification === 'function') {
|
||||
this.showNotification('Applied rewrite for ' + term, 'success', 'fas fa-pen');
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
getVueWatchers() {
|
||||
return {
|
||||
acInput: function() {
|
||||
if (typeof this.acRefreshLexemeAnalysis === 'function') {
|
||||
this.acRefreshLexemeAnalysis();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ class PromptCraftTool extends Tool {
|
||||
pcInput: '',
|
||||
pcOutput: '',
|
||||
pcOutputs: [],
|
||||
pcLexemeAnalysis: { totalFindings: 0, findings: [], summary: 'No Latin-root wording findings.' },
|
||||
pcStrategy: 'rephrase',
|
||||
pcModel: localStorage.getItem('pc-model') || 'nousresearch/hermes-3-llama-3.1-405b',
|
||||
pcTemperature,
|
||||
@@ -78,6 +79,13 @@ class PromptCraftTool extends Tool {
|
||||
}
|
||||
return base;
|
||||
},
|
||||
pcRefreshLexemeAnalysis: function() {
|
||||
if (typeof window === 'undefined' || !window.LexemeAnalysis || typeof window.LexemeAnalysis.analyze !== 'function') {
|
||||
this.pcLexemeAnalysis = { totalFindings: 0, findings: [], summary: 'Lexeme analysis unavailable.' };
|
||||
return;
|
||||
}
|
||||
this.pcLexemeAnalysis = window.LexemeAnalysis.analyze(this.pcInput);
|
||||
},
|
||||
pcRunMutation: async function() {
|
||||
const apiKey = this.pcGetApiKey();
|
||||
if (!apiKey) {
|
||||
@@ -163,6 +171,39 @@ class PromptCraftTool extends Tool {
|
||||
},
|
||||
pcUseAsInput: function(text) {
|
||||
this.pcInput = text;
|
||||
},
|
||||
pcGetLexemeAnalysis: function() {
|
||||
return this.pcLexemeAnalysis || { totalFindings: 0, findings: [], summary: 'No Latin-root wording findings.' };
|
||||
},
|
||||
pcNeutralizeInput: function() {
|
||||
const analysis = this.pcGetLexemeAnalysis();
|
||||
if (!analysis.totalFindings || !window.LexemeAnalysis || typeof window.LexemeAnalysis.neutralizeText !== 'function') {
|
||||
return;
|
||||
}
|
||||
this.pcInput = window.LexemeAnalysis.neutralizeText(this.pcInput, analysis);
|
||||
if (typeof this.showNotification === 'function') {
|
||||
this.showNotification('Applied neutral Latin-root rewrites', 'success', 'fas fa-seedling');
|
||||
}
|
||||
},
|
||||
pcApplyLexemeRewrite: function(term, rewrite) {
|
||||
if (!term || !rewrite) {
|
||||
return;
|
||||
}
|
||||
const escapedTerm = String(term).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
this.pcInput = this.pcInput.replace(new RegExp('\\b' + escapedTerm + '\\b', 'i'), rewrite);
|
||||
if (typeof this.showNotification === 'function') {
|
||||
this.showNotification('Applied rewrite for ' + term, 'success', 'fas fa-pen');
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
getVueWatchers() {
|
||||
return {
|
||||
pcInput: function() {
|
||||
if (typeof this.pcRefreshLexemeAnalysis === 'function') {
|
||||
this.pcRefreshLexemeAnalysis();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user