mirror of
https://github.com/Heretek-AI/openclaw.git
synced 2026-07-19 21:53:30 -04:00
a9ae1a6778
Matrix Protocol: - docker-compose.matrix.yml: Dendrite homeserver + PostgreSQL + Nginx TLS - src/channels/plugins/matrix-channel.ts: OpenClaw plugin implementation - docs/matrix-triad-setup.md: Setup guide with auth scheme (@tm1-4:triad.local) MCP Server Integration: - docs/mcp-triad-integration.md: SearXNG, Playwright, GitHub MCP configs - docs/mcp-curiosity-mapping.md: Gap-to-capability mapping Node Sync Architecture: - src/services/node-sync-service.ts: WebSocket peer sync + presence detection - src/services/node-sync-service.test.ts: Unit tests - docs/node-sync-architecture.md: Architecture docs Triad Resilience: - scripts/triad-corruption-check.mjs: SQLite + log + config + git integrity - docs/triad-resilience.md: Recovery procedures - .secure/deployment-logs/README.md: Schema v2 - skills/triad-heartbeat/SKILL.md: Corruption check integration NPM Publish Workflow: - scripts/npm-publish.mjs: version, changelog, validate, publish, rollback - .github/workflows/npm-publish.yml: GitHub Actions with provenance - docs/npm-publish-guide.md: Complete documentation All deliverables tested in Docker before production.
177 lines
4.6 KiB
JavaScript
Executable File
177 lines
4.6 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
// NLP Guardrails — Content Filtering & Validation for Triad Communication
|
|
// Ensures messages meet "speak only on update" discipline before posting
|
|
|
|
import fs from "fs";
|
|
import path from "path";
|
|
import { fileURLToPath } from "url";
|
|
|
|
const __filename = fileURLToPath(import.meta.url);
|
|
const __dirname = path.dirname(__filename);
|
|
|
|
const WORKSPACE_ROOT = process.env.WORKSPACE_ROOT || "/home/openclaw/.openclaw/workspace";
|
|
const SIGNAL_FILTER_SKILL = path.join(WORKSPACE_ROOT, "skills/triad-signal-filter/SKILL.md");
|
|
|
|
// Banned phrases (echo loops, ritual phrases, noise)
|
|
const BANNED_PHRASES = [
|
|
"standing by",
|
|
"done",
|
|
"aligned",
|
|
"🦞",
|
|
"the third path",
|
|
"together once",
|
|
"awaiting",
|
|
"waiting",
|
|
"ready",
|
|
"acknowledged",
|
|
"copy that",
|
|
"roger",
|
|
"over",
|
|
];
|
|
|
|
// Required content markers (genuine progress, status changes, verification)
|
|
const REQUIRED_MARKERS = [
|
|
"completed",
|
|
"verified",
|
|
"detected",
|
|
"changed",
|
|
"updated",
|
|
"fixed",
|
|
"deployed",
|
|
"synced",
|
|
"hash:",
|
|
"commit:",
|
|
"error:",
|
|
"warning:",
|
|
"report:",
|
|
"metric:",
|
|
"score:",
|
|
];
|
|
|
|
// Check if message contains genuine information
|
|
function hasGenuineContent(message) {
|
|
const lower = message.toLowerCase();
|
|
|
|
// Check for banned phrases
|
|
for (const phrase of BANNED_PHRASES) {
|
|
if (lower.includes(phrase)) {
|
|
return { pass: false, reason: `Banned phrase: "${phrase}"` };
|
|
}
|
|
}
|
|
|
|
// Check for required markers
|
|
for (const marker of REQUIRED_MARKERS) {
|
|
if (lower.includes(marker)) {
|
|
return { pass: true, reason: `Contains marker: "${marker}"` };
|
|
}
|
|
}
|
|
|
|
// Check for numbers/data (git hashes, scores, counts)
|
|
if (/\b[0-9a-f]{7,}\b/.test(lower)) {
|
|
return { pass: true, reason: "Contains data (hash/ID)" };
|
|
}
|
|
|
|
if (/\d+%/.test(lower)) {
|
|
return { pass: true, reason: "Contains metric (%)" };
|
|
}
|
|
|
|
if (/count:|total:|items:|files:/.test(lower)) {
|
|
return { pass: true, reason: "Contains quantifier" };
|
|
}
|
|
|
|
return { pass: false, reason: "No genuine content markers" };
|
|
}
|
|
|
|
// Validate message before posting
|
|
function validateMessage(message, context = {}) {
|
|
console.log("🦞 === NLP Guardrail Check ===");
|
|
console.log(`Message: ${message.slice(0, 80)}${message.length > 80 ? "..." : ""}`);
|
|
console.log("");
|
|
|
|
const result = hasGenuineContent(message);
|
|
|
|
if (!result.pass) {
|
|
console.log(`❌ BLOCKED: ${result.reason}`);
|
|
console.log("");
|
|
console.log("Discipline: Signal > noise. Speak only on update.");
|
|
return { allowed: false, reason: result.reason };
|
|
}
|
|
|
|
// Additional context checks
|
|
if (context.isEcho === true) {
|
|
console.log("❌ BLOCKED: Echo detected (identical to previous message)");
|
|
return { allowed: false, reason: "Echo loop prevention" };
|
|
}
|
|
|
|
if (context.isRateLimitError === true) {
|
|
console.log("❌ BLOCKED: Rate limit error (log locally instead)");
|
|
return { allowed: false, reason: "Rate limit discipline" };
|
|
}
|
|
|
|
console.log(`✅ ALLOWED: ${result.reason}`);
|
|
console.log("");
|
|
console.log("Message contains genuine progress, status change, or novel information.");
|
|
return { allowed: true, reason: result.reason };
|
|
}
|
|
|
|
// Batch validate messages (for triad coordination)
|
|
function batchValidate(messages) {
|
|
console.log("🦞 === Batch Validation ===");
|
|
console.log(`Checking ${messages.length} messages...`);
|
|
console.log("");
|
|
|
|
const results = [];
|
|
let allowed = 0;
|
|
let blocked = 0;
|
|
|
|
for (const msg of messages) {
|
|
const result = validateMessage(msg.text, msg.context || {});
|
|
results.push(result);
|
|
if (result.allowed) {
|
|
allowed++;
|
|
} else {
|
|
blocked++;
|
|
}
|
|
}
|
|
|
|
console.log("");
|
|
console.log(`Results: ${allowed} allowed, ${blocked} blocked`);
|
|
|
|
return results;
|
|
}
|
|
|
|
// CLI mode
|
|
function runCLI() {
|
|
const args = process.argv.slice(2);
|
|
|
|
if (args.length === 0) {
|
|
console.log("Usage: node scripts/nlp-guardrails.js <message>");
|
|
console.log(" node scripts/nlp-guardrails.js --batch <json-file>");
|
|
process.exit(1);
|
|
}
|
|
|
|
if (args[0] === "--batch") {
|
|
const batchFile = args[1];
|
|
if (!batchFile || !fs.existsSync(batchFile)) {
|
|
console.log("❌ Batch file not found");
|
|
process.exit(1);
|
|
}
|
|
|
|
const messages = JSON.parse(fs.readFileSync(batchFile, "utf8"));
|
|
const results = batchValidate(messages);
|
|
process.exit(results.every((r) => r.allowed) ? 0 : 1);
|
|
}
|
|
|
|
// Single message validation
|
|
const message = args.join(" ");
|
|
const result = validateMessage(message);
|
|
process.exit(result.allowed ? 0 : 1);
|
|
}
|
|
|
|
// Export for programmatic use
|
|
if (process.argv[1].endsWith("nlp-guardrails.js")) {
|
|
runCLI();
|
|
}
|
|
|
|
export { validateMessage, batchValidate, hasGenuineContent };
|