feat(governance): architectural enforcement of handoff document reading (inst_083)
Problem: Claude Code was skipping handoff documents despite explicit instructions in
SESSION_CLOSEDOWN_*.md files. This is a 27027-style pattern recognition failure where
the learned pattern "Warmup → run session-init → report ready" overrode the explicit
instruction to read handoff documents.
Root Cause: Voluntary compliance failure - relying on Claude to remember to read
handoff documents after running session-init.js.
Solution: Architectural enforcement via auto-injection
Implementation:
- Modified scripts/session-init.js to automatically detect and parse SESSION_CLOSEDOWN_*.md
- Section 1a now extracts and displays:
• Priorities from previous session
• Recent commits (recent work)
• Known issues/blockers
• Cleanup summary
- Handoff context injected into session-init output automatically
- No voluntary compliance needed - information appears unavoidably
New Instruction (inst_083):
- Quadrant: SYSTEM
- Persistence: HIGH
- Scope: PERMANENT
- Verification: MANDATORY
- Documents architectural enforcement mechanism
- Synced to MongoDB database
Testing:
- Verified with current session handoff (SESSION_CLOSEDOWN_2025-10-25.md)
- Successfully extracted priorities: "Review framework performance, Continue development work"
- Successfully extracted recent work: RESEARCH_DOCUMENTATION_PLAN.md commit (a3329ff)
- Successfully extracted cleanup: 8 background processes killed
Impact:
- Prevents loss of session context across sessions/compaction
- Makes handoff priorities unavoidable (appears in session-init output)
- Architectural solution to procedural compliance problem
Related: inst_077 (session-closedown.js), SESSION_MANAGEMENT_ARCHITECTURE.md
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
a3329fff3e
commit
0688a23c03
2 changed files with 176 additions and 0 deletions
105
scripts/add-inst-083-handoff-injection.js
Normal file
105
scripts/add-inst-083-handoff-injection.js
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Add inst_083: Handoff Auto-Injection
|
||||
*
|
||||
* Adds instruction documenting the architectural enforcement
|
||||
* of handoff document reading via session-init.js auto-injection.
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const INSTRUCTION_HISTORY_PATH = path.join(__dirname, '../.claude/instruction-history.json');
|
||||
|
||||
// New instruction
|
||||
const inst_083 = {
|
||||
"id": "inst_083",
|
||||
"text": "session-init.js MUST automatically extract and display handoff context from SESSION_CLOSEDOWN_*.md files. Prevents 27027-style pattern recognition failures where Claude skips reading handoff documents. Architectural enforcement: handoff context auto-injected into session-init output (section 1a), displaying priorities, recent work, known issues, and cleanup status. No voluntary compliance needed - information appears in context automatically.",
|
||||
"timestamp": new Date().toISOString(),
|
||||
"quadrant": "SYSTEM",
|
||||
"persistence": "HIGH",
|
||||
"temporal_scope": "PERMANENT",
|
||||
"verification_required": "MANDATORY",
|
||||
"explicitness": 0.98,
|
||||
"source": "framework",
|
||||
"session_id": "2025-10-25-handoff-auto-injection",
|
||||
"parameters": {
|
||||
"script": "scripts/session-init.js",
|
||||
"section": "1a",
|
||||
"handoff_pattern": "SESSION_CLOSEDOWN_*.md",
|
||||
"extracted_sections": [
|
||||
"priorities",
|
||||
"recent_commits",
|
||||
"known_issues",
|
||||
"cleanup_summary"
|
||||
],
|
||||
"enforcement_type": "architectural"
|
||||
},
|
||||
"active": true,
|
||||
"notes": "Architectural prevention of handoff skipping. Addresses observed failure where Claude ran session-init but didn't read SESSION_CLOSEDOWN_2025-10-25.md, missing context about RESEARCH_DOCUMENTATION_PLAN.md and previous session priorities. Auto-injection makes handoff unavoidable."
|
||||
};
|
||||
|
||||
try {
|
||||
// Load instruction history
|
||||
const history = JSON.parse(fs.readFileSync(INSTRUCTION_HISTORY_PATH, 'utf8'));
|
||||
|
||||
// Check if inst_083 already exists
|
||||
const exists = history.instructions.some(i => i.id === 'inst_083');
|
||||
|
||||
if (exists) {
|
||||
console.log('⚠️ inst_083 already exists - skipping');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Add instruction
|
||||
history.instructions.push(inst_083);
|
||||
|
||||
// Update metadata
|
||||
history.last_updated = new Date().toISOString();
|
||||
history.version = "4.1";
|
||||
|
||||
// Update stats
|
||||
if (!history.stats) {
|
||||
history.stats = {
|
||||
total_instructions: 0,
|
||||
active_instructions: 0,
|
||||
by_quadrant: {},
|
||||
by_persistence: {}
|
||||
};
|
||||
}
|
||||
|
||||
const activeInstructions = history.instructions.filter(i => i.active);
|
||||
history.stats.total_instructions = history.instructions.length;
|
||||
history.stats.active_instructions = activeInstructions.length;
|
||||
|
||||
// Recalculate quadrant stats
|
||||
history.stats.by_quadrant = {};
|
||||
activeInstructions.forEach(inst => {
|
||||
history.stats.by_quadrant[inst.quadrant] = (history.stats.by_quadrant[inst.quadrant] || 0) + 1;
|
||||
});
|
||||
|
||||
// Recalculate persistence stats
|
||||
history.stats.by_persistence = {};
|
||||
activeInstructions.forEach(inst => {
|
||||
history.stats.by_persistence[inst.persistence] = (history.stats.by_persistence[inst.persistence] || 0) + 1;
|
||||
});
|
||||
|
||||
// Write back
|
||||
fs.writeFileSync(INSTRUCTION_HISTORY_PATH, JSON.stringify(history, null, 2));
|
||||
|
||||
console.log('✅ Added inst_083: Handoff Auto-Injection');
|
||||
console.log('');
|
||||
console.log('Stats:');
|
||||
console.log(` Total instructions: ${history.stats.total_instructions}`);
|
||||
console.log(` Active instructions: ${history.stats.active_instructions}`);
|
||||
console.log(` SYSTEM quadrant: ${history.stats.by_quadrant.SYSTEM || 0}`);
|
||||
console.log(` HIGH persistence: ${history.stats.by_persistence.HIGH || 0}`);
|
||||
console.log('');
|
||||
console.log('Next: Sync to database with:');
|
||||
console.log(' node scripts/sync-instructions-to-db.js --force');
|
||||
|
||||
} catch (err) {
|
||||
console.error('❌ Error:', err.message);
|
||||
process.exit(1);
|
||||
}
|
||||
|
|
@ -326,6 +326,77 @@ async function main() {
|
|||
}
|
||||
}
|
||||
|
||||
// Check for handoff documents (inst_083: Auto-inject handoff context)
|
||||
section('1a. Previous Session Handoff Detection');
|
||||
try {
|
||||
const handoffFiles = fs.readdirSync(path.join(__dirname, '..'))
|
||||
.filter(f => f.startsWith('SESSION_CLOSEDOWN_') && f.endsWith('.md'))
|
||||
.sort()
|
||||
.reverse();
|
||||
|
||||
if (handoffFiles.length > 0) {
|
||||
const latestHandoff = handoffFiles[0];
|
||||
const handoffPath = path.join(__dirname, '..', latestHandoff);
|
||||
const handoffContent = fs.readFileSync(handoffPath, 'utf8');
|
||||
|
||||
console.log('');
|
||||
log('═'.repeat(70), 'yellow');
|
||||
warning(`📄 PREVIOUS SESSION HANDOFF: ${latestHandoff}`);
|
||||
log('═'.repeat(70), 'yellow');
|
||||
console.log('');
|
||||
|
||||
// Extract and display Priorities section
|
||||
const prioritiesMatch = handoffContent.match(/\*\*Priorities\*\*:([\s\S]*?)(?=\n##|\n---|\n\*\*|$)/);
|
||||
if (prioritiesMatch) {
|
||||
log(' 📋 PRIORITIES FROM PREVIOUS SESSION:', 'bright');
|
||||
const priorities = prioritiesMatch[1].trim().split('\n').filter(line => line.trim());
|
||||
priorities.forEach(priority => {
|
||||
log(` ${priority.trim()}`, 'yellow');
|
||||
});
|
||||
console.log('');
|
||||
}
|
||||
|
||||
// Extract and display Recent Commits (recent work)
|
||||
const commitsMatch = handoffContent.match(/\*\*Recent Commits\*\*:\s*```([\s\S]*?)```/);
|
||||
if (commitsMatch) {
|
||||
log(' 📝 RECENT WORK (Last Commits):', 'bright');
|
||||
const commits = commitsMatch[1].trim().split('\n').filter(line => line.trim()).slice(0, 3);
|
||||
commits.forEach(commit => {
|
||||
log(` ${commit.trim()}`, 'cyan');
|
||||
});
|
||||
console.log('');
|
||||
}
|
||||
|
||||
// Extract and display Known Issues/Blockers
|
||||
const issuesMatch = handoffContent.match(/\*\*Known Issues\*\*:([\s\S]*?)(?=\n##|\n---|\n\*\*|$)/);
|
||||
if (issuesMatch) {
|
||||
log(' ⚠️ KNOWN ISSUES:', 'bright');
|
||||
const issues = issuesMatch[1].trim().split('\n').filter(line => line.trim());
|
||||
issues.forEach(issue => {
|
||||
log(` ${issue.trim()}`, 'red');
|
||||
});
|
||||
console.log('');
|
||||
}
|
||||
|
||||
// Extract cleanup summary
|
||||
const cleanupMatch = handoffContent.match(/Background processes killed:\s+(\d+)/);
|
||||
if (cleanupMatch) {
|
||||
log(` 🧹 Previous session cleanup: ${cleanupMatch[1]} background processes killed`, 'cyan');
|
||||
console.log('');
|
||||
}
|
||||
|
||||
log('═'.repeat(70), 'yellow');
|
||||
log(' HANDOFF CONTEXT LOADED - Continue with priorities above', 'green');
|
||||
log('═'.repeat(70), 'yellow');
|
||||
console.log('');
|
||||
|
||||
} else {
|
||||
log(' No recent handoff documents found - fresh start', 'cyan');
|
||||
}
|
||||
} catch (handoffErr) {
|
||||
warning(`Could not load handoff document: ${handoffErr.message}`);
|
||||
}
|
||||
|
||||
// Reset checkpoints for new day
|
||||
section('2. Resetting Token Checkpoints');
|
||||
const checkpoints = resetTokenCheckpoints();
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue