fix: integrate audit findings round 1 - tools, worker, scheduler, main agent

- Unify ToolResultEnvelope (output vs content) for built-in tools
- Fix shell.run AsyncGenerator consumption in ToolRegistry.call/streaming
- Scheduler: consume WorkerResult.status instead of marking all running tasks completed
- WorkerProcess/WorkerManager: surface exit events and generate failed/cancelled result
- MainAgent: integrate ContextAssembler, Chinese destructive regex, ArchitectureDesigner impact gate
- run.ts: pendingConfirmation flow, dispatch extracted, .air files filtered from /results
- CapabilityRegistry wired into RuntimeApp and ServiceRegistry; DoctorService uses it
- release.ts: findRepoRoot/findBun, run air e2e + depcruise + runtime regression
- New gates: release-critical-gates, CLI run command regression
- 14/14 e2e gates pass; 3/3 release dry-run pass

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
AirCoding
2026-06-05 18:39:10 +08:00
parent a2d7aa0339
commit ddefcbb2b1
24 changed files with 1992 additions and 186 deletions

View File

@@ -43,14 +43,12 @@ export function createShellExecutor(project_root: string) {
const cwd = workdir || project_root
const timestamp = new Date().toISOString() as ISOTimeString
// Emit command.started event
yield {
status: 'ok',
output: { event: 'command.started', command, cwd },
metadata: { timestamp, streaming: true, call_id: call.call_id, tool_name: 'shell.run' }
}
// Execute command
const proc = spawn(command, [], {
cwd,
shell: true,
@@ -59,53 +57,81 @@ export function createShellExecutor(project_root: string) {
let stdout = ''
let stderr = ''
let final_code = 0
let timed_out = false
const chunks: ToolResultEnvelope[] = []
// Stream stdout
proc.stdout.on('data', (data) => {
const text = data.toString()
stdout += text
// Emit streaming stdout
// Note: In actual implementation, this would go through EventBus
chunks.push({
status: 'ok',
output: { event: 'command.stdout', text },
metadata: { timestamp: new Date().toISOString() as ISOTimeString, streaming: true, call_id: call.call_id, tool_name: 'shell.run' }
})
})
// Stream stderr
proc.stderr.on('data', (data) => {
const text = data.toString()
stderr += text
chunks.push({
status: 'ok',
output: { event: 'command.stderr', text },
metadata: { timestamp: new Date().toISOString() as ISOTimeString, streaming: true, call_id: call.call_id, tool_name: 'shell.run' }
})
})
// Wait for completion or timeout
let timed_out = false
const timeoutPromise = new Promise<number>((resolve) => {
setTimeout(() => {
timed_out = true
proc.kill('SIGKILL')
resolve(124) // standard timeout exit code
}, timeout)
const timeout_id = setTimeout(() => {
timed_out = true
proc.kill('SIGKILL')
}, timeout)
const exit_code = await new Promise<number>((resolve) => {
proc.on('exit', (code) => resolve(code ?? 0))
proc.on('error', () => resolve(1))
})
clearTimeout(timeout_id)
const exitCode = await Promise.race([
new Promise<number>((resolve) => proc.on('exit', (code) => resolve(code || 0))),
timeoutPromise
])
if (stdout) {
yield {
status: 'ok',
output: { event: 'command.stdout', text: stdout.slice(-50000) },
metadata: { timestamp: new Date().toISOString() as ISOTimeString, streaming: true, call_id: call.call_id, tool_name: 'shell.run' }
}
}
if (stderr) {
yield {
status: 'ok',
output: { event: 'command.stderr', text: stderr.slice(-10000) },
metadata: { timestamp: new Date().toISOString() as ISOTimeString, streaming: true, call_id: call.call_id, tool_name: 'shell.run' }
}
}
while (chunks.length > 0) {
yield chunks.shift()!
}
final_code = exitCode
if (timed_out) {
stderr += `\n[Command timed out after ${timeout}ms]`
}
// Emit command.completed event
yield {
status: final_code === 0 ? 'ok' : 'error',
status: exit_code === 0 ? 'ok' : 'error',
output: {
event: 'command.completed',
exit_code: final_code,
stdout: stdout.slice(-50000), // Last 50KB
stderr: stderr.slice(-10000), // Last 10KB
exit_code,
stdout: stdout.slice(-50000),
stderr: stderr.slice(-10000),
timed_out
},
metadata: { timestamp: new Date().toISOString() as ISOTimeString, streaming: false }
error: exit_code === 0 ? undefined : {
error_id: call.call_id,
kind: 'tool_error',
severity: 'error',
message: timed_out ? `Command timed out after ${timeout}ms` : `Command exited with code ${exit_code}`,
retryability: timed_out ? 'retryable' : 'not_retryable',
semantic_signature: 'shell.run'
},
metadata: { timestamp: new Date().toISOString() as ISOTimeString, streaming: false, is_final: true, call_id: call.call_id, tool_name: 'shell.run' }
}
}
}