tractatus/scripts/audit-card-category-sequences.js
TheFlow deefb753f7 feat(quality): add document quality audit and resequencing scripts
- audit-inflection-point.js: Identify fictional content in research paper
- fix-inflection-point-fiction.js: Remove fabricated statistics
- audit-all-card-sequences.js: Check card sequence quality
- audit-card-category-sequences.js: Analyze pedagogical flow
- resequence-cards-pedagogically.js: Reorder cards for better learning flow
- apply-production-fixes.js: Production deployment script
- inspect-*: Helper scripts for analysis

Quality improvements:
- Removed fictional content from Inflection Point document (3 sections)
- Resequenced 21 documents pedagogically (22-67% jumpiness reduction)
- Implemented proper learning flow: concepts → warnings → technical → reference
2025-10-25 22:40:36 +13:00

167 lines
6 KiB
JavaScript

/**
* Audit card category sequences across all public documents
* Show pedagogical flow issues
*/
const { MongoClient } = require('mongodb');
const PUBLIC_SLUGS = [
'introduction', 'core-concepts', 'executive-summary-tractatus-inflection-point',
'implementation-guide-v1.1', 'implementation-guide', 'implementation-guide-python-examples',
'tractatus-framework-research', 'pluralistic-values-research-foundations',
'the-27027-incident-a-case-study-in-pattern-recognition-bias',
'real-world-ai-governance-a-case-study-in-framework-failure-and-recovery',
'llm-integration-feasibility-research-scope',
'research-topic-concurrent-session-architecture',
'research-topic-rule-proliferation-transactional-overhead',
'technical-architecture', 'api-reference-complete', 'api-javascript-examples',
'api-python-examples', 'openapi-specification',
'value-pluralism-faq', 'tractatus-ai-safety-framework-core-values-and-principles',
'organizational-theory-foundations', 'business-case-tractatus-framework'
];
const CATEGORY_ICONS = {
'conceptual': '📘',
'technical': '🔧',
'practical': '💡',
'reference': '📋',
'critical': '⚠️'
};
function analyzeSequence(sections) {
if (!sections || sections.length === 0) return null;
const sequence = sections.map(s => s.category);
const categoryChanges = [];
for (let i = 1; i < sequence.length; i++) {
if (sequence[i] !== sequence[i-1]) {
categoryChanges.push(i);
}
}
// Calculate "jumpiness" - how often categories change
const jumpiness = categoryChanges.length / (sections.length - 1);
// Identify poor patterns
const issues = [];
// Issue 1: Critical/warning at the end (should be near start)
const criticalIndices = sequence.map((cat, idx) => cat === 'critical' ? idx : -1).filter(i => i >= 0);
if (criticalIndices.some(idx => idx > sequence.length * 0.7)) {
issues.push('Critical content appears late in sequence');
}
// Issue 2: Reference at the beginning (should be at end)
const referenceIndices = sequence.map((cat, idx) => cat === 'reference' ? idx : -1).filter(i => i >= 0);
if (referenceIndices.some(idx => idx < sequence.length * 0.3)) {
issues.push('Reference content appears early (should be at end)');
}
// Issue 3: Technical before conceptual (usually bad pedagogy)
for (let i = 0; i < sequence.length - 1; i++) {
if (sequence[i] === 'technical' && i < 2) {
issues.push('Technical content appears before conceptual foundation');
break;
}
}
// Issue 4: High jumpiness (categories bouncing around)
if (jumpiness > 0.6) {
issues.push(`High category jumpiness (${Math.round(jumpiness * 100)}%) - cards bounce between types`);
}
return {
sequence,
categoryChanges: categoryChanges.length,
jumpiness: Math.round(jumpiness * 100),
issues
};
}
async function run() {
const client = new MongoClient('mongodb://localhost:27017');
await client.connect();
const db = client.db('tractatus_dev');
const collection = db.collection('documents');
console.log('═══════════════════════════════════════════════════════════');
console.log(' CARD CATEGORY SEQUENCE AUDIT');
console.log('═══════════════════════════════════════════════════════════\n');
const poorSequences = [];
for (const slug of PUBLIC_SLUGS) {
const doc = await collection.findOne({ slug });
if (!doc || !doc.sections) continue;
console.log(`\n📄 ${doc.title}`);
console.log(` Slug: ${slug}`);
console.log(` Category: ${doc.category || 'none'}`);
console.log(` Cards: ${doc.sections.length}`);
const analysis = analyzeSequence(doc.sections);
if (!analysis) {
console.log(' ❌ No sections to analyze');
continue;
}
// Show category sequence visually
console.log(`\n Sequence:`);
const sequenceDisplay = analysis.sequence.map((cat, idx) => {
const icon = CATEGORY_ICONS[cat] || '❓';
return `${icon} ${cat}`;
}).join(' → ');
// Wrap long sequences
const parts = [];
let currentPart = '';
analysis.sequence.forEach((cat, idx) => {
const icon = CATEGORY_ICONS[cat] || '❓';
const item = `${icon}`;
if (currentPart.length + item.length > 50) {
parts.push(currentPart);
currentPart = ' ';
}
currentPart += item + ' ';
});
if (currentPart.trim()) parts.push(currentPart);
parts.forEach(part => console.log(part));
console.log(`\n Metrics:`);
console.log(` - Category changes: ${analysis.categoryChanges}`);
console.log(` - Jumpiness: ${analysis.jumpiness}%`);
if (analysis.issues.length > 0) {
console.log(`\n ⚠️ ISSUES:`);
analysis.issues.forEach(issue => console.log(` - ${issue}`));
poorSequences.push({ slug, doc: doc.title, issues: analysis.issues });
} else {
console.log(`\n ✅ Sequence looks reasonable`);
}
}
console.log('\n\n═══════════════════════════════════════════════════════════');
console.log(' SUMMARY');
console.log('═══════════════════════════════════════════════════════════\n');
console.log(`Documents audited: ${PUBLIC_SLUGS.length}`);
console.log(`Documents with poor sequences: ${poorSequences.length}\n`);
if (poorSequences.length > 0) {
console.log('Documents needing resequencing:\n');
poorSequences.forEach((item, idx) => {
console.log(`${idx + 1}. ${item.doc}`);
console.log(` Slug: ${item.slug}`);
item.issues.forEach(issue => console.log(` - ${issue}`));
console.log('');
});
}
await client.close();
}
run().catch(console.error);