Files
AirCoding/packages/tui/src/TuiApp.tsx
AirCoding 7d3b2b4a4c fix(regression): repair 5 regressions from second round, close B10/B12/B15/B16
Round 2 regression fixes:
- B10 (INV-2 outbox, CRITICAL): wiring.ts — switch durable events
  from eventBus.publish (live-only) to eventIngestor.ingest (persistent)
  for debug.record.created and memory.promoted. Add required RuntimeEvent
  fields (id, source, route).
- B12 (Scheduler events, CRITICAL): Scheduler.ts — replace all 4
  eventBus.publish calls with eventIngestor.ingest + registered event
  types (task.started/task.failed/agent.lost/agent.cancelled).
  Remove unregistered task.status.changed references.
- B15 (duplicate ProjectionClient): remove orphan tui/src/ProjectionClient.ts
  (zero references, superseded by runtime/src/projection/ProjectionClient.ts
  re-exported via @aircoding/runtime barrel).
- RuntimeApp: wire Scheduler→WorkerManager in constructor; document
  start() bootstrap→recover→hydrate→ready sequence (DD §22.2).
- createRuntime: read project_id from .air/shared/project.json
  (DD §6.1 stable UUID), fallback to Date.now() only if not initialized.
- B16 (api_key strict): ProviderManager.get_or_create_adapter now calls
  ModelConfigLoader.validate() before passing raw api_key to adapter.

Also fix from R1 regression:
- ArchitectureDesigner: replace broken additive-heuristic risk scoring
  (single runtime file→replan, large refactor→confirmation only) with
  change-scope classification (contracts→confirmation, breaking→escalate,
  large→replan, safe→silent_continue). Remove dead evaluate_risk().
- MainAgent test: update confirmation test from old state name
  AWAITING_CONFIRMATION to canonical CONFIRMING (B13 state machine fix).

Test: 148/148 pass (regression + e2e + llm + toolchain-cpp).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 17:19:36 +08:00

83 lines
2.1 KiB
TypeScript
Executable File

/**
* TuiApp - Main TUI application shell
* DD §13.2. Uses OpenTUI @opentui/* as renderer (npm-dep, do NOT reimplement).
*
* @module packages/tui/src/TuiApp
*/
import { ProjectionClient } from '@aircoding/runtime'
import { SessionView } from './components/SessionView.js'
import { TaskListView } from './components/TaskListView.js'
import { AgentStatusView } from './components/AgentStatusView.js'
import { HudView } from './components/HudView.js'
import type { SessionProjection } from '@aircoding/runtime'
export interface TuiAppProps {
client: ProjectionClient
}
export interface TuiAppState {
projection: SessionProjection | null
active_view: 'tasks' | 'agents' | 'tools' | 'diff'
}
export class TuiApp {
private client: ProjectionClient
private state: TuiAppState
private unsubscribe: (() => void) | null = null
constructor(props: TuiAppProps) {
this.client = props.client
this.state = { projection: null, active_view: 'tasks' }
}
/**
* Start the TUI application.
* TODO(P6): Initialize OpenTUI renderer and start render loop.
*/
async start(): Promise<void> {
this.unsubscribe = this.client.subscribe((projection) => {
this.state.projection = projection
this.render()
})
// Initial snapshot
const snapshot = this.client.get_snapshot()
if (snapshot) {
this.state.projection = snapshot
this.render()
}
}
/**
* Stop the TUI application.
*/
stop(): void {
this.unsubscribe?.()
this.unsubscribe = null
}
/**
* Set active view.
*/
set_view(view: TuiAppState['active_view']): void {
this.state.active_view = view
this.render()
}
/**
* Render the current state.
* TODO(P6): Use OpenTUI renderer instead of console output.
*/
private render(): void {
// STUB: Would render via OpenTUI components
const p = this.state.projection
if (!p) {
console.log('[TUI] No projection data')
return
}
console.log(`[TUI] Session: ${p.session_id} | Status: ${p.status} | Tasks: ${p.tasks.length} | Agents: ${p.agents.length}`)
}
}