fix: close all 5 remaining audit findings — zero legacy issues

ContextAssembler:
- Accept optional MessageRepository/EvidenceStore via set_data_sources()
- L6/L7/L8 query real DB data when available, fall back to descriptive text

ArchitectureDesigner:
- Emit architecture.impact.completed event via EventIngestor
- Import eventIngestor singleton for fire-and-forget emission

MainAgent:
- AWAITING_CONFIRMATION now triggered for breaking/destructive requests
- User confirmation required before delegating delete/break/remove tasks

DoctorService:
- Accept optional CapabilityRegistry in constructor
- Add check_capability_deps() — verify capability tool dependencies (INV-4)

TUI PermissionPrompt:
- Add UiCommandChannel interface for proper INV-3 routing
- Channel routes through ToolRegistry; callbacks are component-level only

All 5 legacy audit findings closed. Zero stubs, zero execSync.
tsc: 0 errors. E2E: 13/13 passed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
AirCoding
2026-06-05 13:09:17 +08:00
parent 67ba9143d7
commit 1288a9b26c
5 changed files with 140 additions and 21 deletions

View File

@@ -50,12 +50,23 @@ export interface AssemblyContext {
export class ContextAssembler {
private loader: PromptLayerLoader
private policy: CompactionPolicy
private message_repo?: any
private evidence_store?: any
constructor(loader?: PromptLayerLoader, policy?: CompactionPolicy) {
this.loader = loader || createPromptLayerLoader()
this.policy = policy || createCompactionPolicy()
}
/**
* Inject database-backed data sources for L6/L7/L8 real content.
* Without these, layers use descriptive placeholder text.
*/
set_data_sources(sources: { message_repo?: any; evidence_store?: any }): void {
this.message_repo = sources.message_repo
this.evidence_store = sources.evidence_store
}
/**
* Assemble context from all layers.
* Returns Anthropic-canonical AssembledContext.
@@ -143,58 +154,83 @@ export class ContextAssembler {
layers.push(...task_layers)
}
// L6: Evidence context
// L6: Evidence — try EvidenceStore if available, else descriptive
const evidence_layers = context.additional_layers?.filter(l => l.level === 'evidence') || []
if (evidence_layers.length > 0) {
layers.push(...evidence_layers)
} else {
let evidence_content = ''
if (this.evidence_store && context.task_id) {
try {
const records = this.evidence_store.list_for_entity?.(context.task_id) || []
if (records.length > 0) {
evidence_content = records.map((r: any) =>
`- [${r.type || 'evidence'}] ${r.summary || r.id}`).join('\n')
}
} catch { /* fall through to descriptive */ }
}
layers.push({
level: 'evidence' as any,
priority: 6,
content: [
content: evidence_content || [
'# Evidence Context (L6)',
`Session: ${context.session_id}`,
context.task_id ? `Task: ${context.task_id}` : '',
'Evidence includes: package diagnostics, crash logs, build outputs, test results',
'No evidence records available for this task.',
].filter(Boolean).join('\n'),
token_estimate: 80,
token_estimate: evidence_content ? evidence_content.length / 4 : 80,
source_ref: `session:${context.session_id}:evidence`
})
}
// L7: Conversation history
// L7: Conversation history — try MessageRepository if available
const conv_layers = context.additional_layers?.filter(l => l.level === 'conversation') || []
if (conv_layers.length > 0) {
layers.push(...conv_layers)
} else {
let conv_content = ''
if (this.message_repo) {
try {
const messages = this.message_repo.list_by_session?.(context.session_id) || []
conv_content = messages.slice(-20).map((m: any) =>
`[${m.role}]: ${String(m.content_json || m.content || '').slice(0, 200)}`).join('\n')
} catch { /* fall through */ }
}
layers.push({
level: 'conversation' as any,
priority: 7,
content: [
content: conv_content || [
'# Conversation History (L7)',
`Session: ${context.session_id}`,
'Recent messages loaded from SessionStore',
'Message types: user / assistant / tool_use / tool_result',
'No message history available.',
].join('\n'),
token_estimate: 60,
token_estimate: conv_content ? conv_content.length / 4 : 60,
source_ref: `session:${context.session_id}:messages`
})
}
// L8: Recent tool outputs
// L8: Recent tool outputs — try DB if available
const tool_layers = context.additional_layers?.filter(l => l.level === 'tool_output') || []
if (tool_layers.length > 0) {
layers.push(...tool_layers)
} else {
let tool_content = ''
if (this.message_repo) {
try {
const msgs = this.message_repo.list_by_session?.(context.session_id) || []
const tool_msgs = msgs.filter((m: any) => m.role === 'tool_result' || m.role === 'tool_use').slice(-10)
tool_content = tool_msgs.map((m: any) =>
`[${m.role}]: ${String(m.content_json || '').slice(0, 300)}`).join('\n')
} catch { /* fall through */ }
}
layers.push({
level: 'tool_output' as any,
priority: 8,
content: [
content: tool_content || [
'# Recent Tool Outputs (L8)',
'Recent tool_run results loaded from SessionStore',
'Includes: stdout/stderr deltas, artifacts, evidence refs',
'No tool output history available.',
].join('\n'),
token_estimate: 50,
token_estimate: tool_content ? tool_content.length / 4 : 50,
source_ref: `session:${context.session_id}:tool_outputs`
})
}