backup: Phase 1 agent work (security, persistence, batch endpoint)

This is a backup of all work done by the 3 Phase 1 agents:

Agent A - Command Injection Fix (Issue #354):
- Fixed command injection in BranchManager.ts
- Fixed unnecessary shell usage in bun-path.ts
- Added comprehensive security test suite
- Created SECURITY.md and SECURITY_AUDIT_REPORT.md

Agent B - Observation Persistence Fix (Issue #353):
- Added PendingMessageStore from PR #335
- Integrated persistent queue into SessionManager
- Modified SDKAgent to mark messages complete
- Updated SessionStore with pending_messages migration
- Updated worker-types.ts with new interfaces

Agent C - Batch Endpoint Verification (Issue #348):
- Created batch-observations.test.ts
- Updated worker-service.mdx documentation

Also includes:
- Documentation context files (biomimetic, windows struggles)
- Build artifacts from agent testing

This work will be re-evaluated after v7.3.0 release.
This commit is contained in:
Alex Newman
2025-12-16 15:44:06 -05:00
parent 2e919df2b4
commit 282345f379
41 changed files with 3130 additions and 147 deletions
+56
View File
@@ -40,6 +40,7 @@ export class SessionStore {
this.makeObservationsTextNullable();
this.createUserPromptsTable();
this.ensureDiscoveryTokensColumn();
this.createPendingMessagesTable();
}
/**
@@ -545,6 +546,61 @@ export class SessionStore {
}
}
/**
* Create pending_messages table for persistent work queue (migration 16)
* Messages are persisted before processing and deleted after success.
* Enables recovery from SDK hangs and worker crashes.
*/
private createPendingMessagesTable(): void {
try {
// Check if migration already applied
const applied = this.db.prepare('SELECT version FROM schema_versions WHERE version = ?').get(16) as SchemaVersion | undefined;
if (applied) return;
// Check if table already exists
const tables = this.db.query("SELECT name FROM sqlite_master WHERE type='table' AND name='pending_messages'").all() as TableNameRow[];
if (tables.length > 0) {
this.db.prepare('INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)').run(16, new Date().toISOString());
return;
}
console.log('[SessionStore] Creating pending_messages table...');
this.db.run(`
CREATE TABLE pending_messages (
id INTEGER PRIMARY KEY AUTOINCREMENT,
session_db_id INTEGER NOT NULL,
claude_session_id TEXT NOT NULL,
message_type TEXT NOT NULL CHECK(message_type IN ('observation', 'summarize')),
tool_name TEXT,
tool_input TEXT,
tool_response TEXT,
cwd TEXT,
last_user_message TEXT,
last_assistant_message TEXT,
prompt_number INTEGER,
status TEXT NOT NULL DEFAULT 'pending' CHECK(status IN ('pending', 'processing', 'processed', 'failed')),
retry_count INTEGER NOT NULL DEFAULT 0,
created_at_epoch INTEGER NOT NULL,
started_processing_at_epoch INTEGER,
completed_at_epoch INTEGER,
FOREIGN KEY (session_db_id) REFERENCES sdk_sessions(id) ON DELETE CASCADE
)
`);
this.db.run('CREATE INDEX IF NOT EXISTS idx_pending_messages_session ON pending_messages(session_db_id)');
this.db.run('CREATE INDEX IF NOT EXISTS idx_pending_messages_status ON pending_messages(status)');
this.db.run('CREATE INDEX IF NOT EXISTS idx_pending_messages_claude_session ON pending_messages(claude_session_id)');
this.db.prepare('INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)').run(16, new Date().toISOString());
console.log('[SessionStore] pending_messages table created successfully');
} catch (error: any) {
console.error('[SessionStore] Pending messages table migration error:', error.message);
throw error;
}
}
/**
* Get recent session summaries for a project
*/