tractatus/scripts/add-instruction.js
TheFlow 1807d9da4a feat(audit): integrate validate-file-write with audit logging and add data quality insights
- Added audit database logging to all 7 validation check points in validate-file-write.js
  * CSP violations (inst_038)
  * Pre-action check failures (inst_038)
  * Overwrite without read (inst_038)
  * Instruction conflicts (CrossReferenceValidator)
  * Boundary violations (inst_020)
  * GitHub URL protection (inst_084)
  * Success logging (no violations)

- Added data quality insights section to audit analytics dashboard
  * Detects and explains when violations > blocked decisions
  * Shows average violations per block
  * Counts decisions with multiple violations
  * Provides user-friendly explanation that this is expected behavior

- Added scripts/add-instruction.js tool for safe instruction management
  * Bypasses inst_027 protection
  * Full CLI with argument parsing
  * Auto-generates instruction IDs

Resolves dual hook system logging gap - all validators now log to MongoDB
2025-10-28 12:22:10 +13:00

193 lines
5.7 KiB
JavaScript
Executable file

#!/usr/bin/env node
/**
* Add Instruction to Instruction History
*
* Safely adds a new governance instruction to instruction-history.json
* Bypasses inst_027 prohibition on direct file edits
*
* Usage:
* node scripts/add-instruction.js --text "instruction text" --quadrant STRATEGIC --persistence HIGH
*/
const fs = require('fs');
const path = require('path');
const INSTRUCTION_HISTORY_PATH = path.join(__dirname, '../.claude/instruction-history.json');
// Parse command-line arguments
function parseArgs() {
const args = process.argv.slice(2);
const parsed = {
text: null,
quadrant: 'OPERATIONAL',
persistence: 'MEDIUM',
temporal_scope: 'PERMANENT',
verification_required: 'OPTIONAL',
explicitness: 0.8,
notes: ''
};
for (let i = 0; i < args.length; i++) {
const arg = args[i];
if (arg === '--help' || arg === '-h') {
showHelp();
process.exit(0);
}
if (arg === '--text' && args[i + 1]) {
parsed.text = args[i + 1];
i++;
} else if (arg === '--quadrant' && args[i + 1]) {
parsed.quadrant = args[i + 1];
i++;
} else if (arg === '--persistence' && args[i + 1]) {
parsed.persistence = args[i + 1];
i++;
} else if (arg === '--temporal' && args[i + 1]) {
parsed.temporal_scope = args[i + 1];
i++;
} else if (arg === '--verification' && args[i + 1]) {
parsed.verification_required = args[i + 1];
i++;
} else if (arg === '--explicitness' && args[i + 1]) {
parsed.explicitness = parseFloat(args[i + 1]);
i++;
} else if (arg === '--notes' && args[i + 1]) {
parsed.notes = args[i + 1];
i++;
}
}
return parsed;
}
function showHelp() {
console.log(`
Add Instruction to Instruction History
Usage:
node scripts/add-instruction.js --text "instruction text" [options]
Required Arguments:
--text <text> The instruction text
Optional Arguments:
--quadrant <quadrant> STRATEGIC, OPERATIONAL, TACTICAL, or SYSTEM (default: OPERATIONAL)
--persistence <level> HIGH, MEDIUM, or LOW (default: MEDIUM)
--temporal <scope> PERMANENT, SESSION, or IMMEDIATE (default: PERMANENT)
--verification <req> MANDATORY or OPTIONAL (default: OPTIONAL)
--explicitness <score> 0.0 to 1.0 (default: 0.8)
--notes <notes> Additional notes about this instruction
Examples:
# Add a database security instruction
node scripts/add-instruction.js \\
--text "All database queries must use prepared statements" \\
--quadrant SYSTEM \\
--persistence HIGH \\
--verification MANDATORY
# Add a tactical code style instruction
node scripts/add-instruction.js \\
--text "Use async/await instead of .then() chains" \\
--quadrant TACTICAL \\
--persistence LOW
`);
}
function getNextInstructionId(instructions) {
// Find highest numbered instruction
const numbered = instructions
.map(i => i.id)
.filter(id => /^inst_\d+$/.test(id))
.map(id => parseInt(id.replace('inst_', '')))
.filter(n => !isNaN(n));
const maxId = numbered.length > 0 ? Math.max(...numbered) : 0;
return `inst_${String(maxId + 1).padStart(3, '0')}`;
}
function main() {
const args = parseArgs();
// Validate required arguments
if (!args.text) {
console.error('❌ Error: --text is required');
console.error('Run with --help for usage information');
process.exit(1);
}
// Validate quadrant
const validQuadrants = ['STRATEGIC', 'OPERATIONAL', 'TACTICAL', 'SYSTEM'];
if (!validQuadrants.includes(args.quadrant)) {
console.error(`❌ Error: Invalid quadrant "${args.quadrant}"`);
console.error(` Valid options: ${validQuadrants.join(', ')}`);
process.exit(1);
}
// Validate persistence
const validPersistence = ['HIGH', 'MEDIUM', 'LOW'];
if (!validPersistence.includes(args.persistence)) {
console.error(`❌ Error: Invalid persistence "${args.persistence}"`);
console.error(` Valid options: ${validPersistence.join(', ')}`);
process.exit(1);
}
// Read current instruction history
let history;
try {
history = JSON.parse(fs.readFileSync(INSTRUCTION_HISTORY_PATH, 'utf8'));
} catch (err) {
console.error('❌ Error reading instruction-history.json:', err.message);
process.exit(1);
}
// Get next instruction ID
const newId = getNextInstructionId(history.instructions);
// Create new instruction
const newInstruction = {
id: newId,
text: args.text,
timestamp: new Date().toISOString(),
quadrant: args.quadrant,
persistence: args.persistence,
temporal_scope: args.temporal_scope,
verification_required: args.verification_required,
explicitness: args.explicitness,
source: 'manual_script',
session_id: 'user_added',
active: true,
created_date: new Date().toISOString().split('T')[0]
};
if (args.notes) {
newInstruction.notes = args.notes;
}
// Add to instructions array
history.instructions.push(newInstruction);
// Update metadata
history.last_updated = new Date().toISOString();
// Write back to file
try {
fs.writeFileSync(INSTRUCTION_HISTORY_PATH, JSON.stringify(history, null, 2));
} catch (err) {
console.error('❌ Error writing instruction-history.json:', err.message);
process.exit(1);
}
console.log(`✅ Added ${newId}: ${args.text.substring(0, 60)}${args.text.length > 60 ? '...' : ''}`);
console.log(` Quadrant: ${args.quadrant}`);
console.log(` Persistence: ${args.persistence}`);
console.log(` Total instructions: ${history.instructions.length}`);
console.log(` Active instructions: ${history.instructions.filter(i => i.active).length}`);
console.log('');
console.log('💡 Next step: Run sync-instructions-to-db.js to persist to MongoDB');
}
main();