Includes AirPlan design documents, AircOding-alpha1-plan, AirPlanV2, AirPlan-ParaV2, AirPlan-Para V1 reference docs, and all working code changes across packages. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
249 lines
18 KiB
TypeScript
Executable File
249 lines
18 KiB
TypeScript
Executable File
/**
|
||
* 诊断脚本 v3:手动建表,遍历全部 58 个 durable event type
|
||
*/
|
||
import { Database } from "bun:sqlite";
|
||
import { EventSchemaRegistry } from "./packages/runtime/src/events/EventSchemaRegistry.js";
|
||
import { EventStore } from "./packages/runtime/src/events/EventStore.js";
|
||
import { EventRepository } from "./packages/runtime/src/storage/repositories/EventRepository.js";
|
||
import { SessionRepository } from "./packages/runtime/src/storage/repositories/SessionRepository.js";
|
||
import { MessageRepository } from "./packages/runtime/src/storage/repositories/MessageRepository.js";
|
||
import { MessageDraftRepository } from "./packages/runtime/src/storage/repositories/MessageDraftRepository.js";
|
||
import { TaskRepository } from "./packages/runtime/src/storage/repositories/TaskRepository.js";
|
||
import { TaskDependencyRepository } from "./packages/runtime/src/storage/repositories/TaskDependencyRepository.js";
|
||
import { TaskAttemptRepository } from "./packages/runtime/src/storage/repositories/TaskAttemptRepository.js";
|
||
import { AgentRepository } from "./packages/runtime/src/storage/repositories/AgentRepository.js";
|
||
import { ToolRunRepository } from "./packages/runtime/src/storage/repositories/ToolRunRepository.js";
|
||
import { CommandRunRepository } from "./packages/runtime/src/storage/repositories/CommandRunRepository.js";
|
||
import { ArtifactRepository } from "./packages/runtime/src/storage/repositories/ArtifactRepository.js";
|
||
import { DiagnosticRepository } from "./packages/runtime/src/storage/repositories/DiagnosticRepository.js";
|
||
import { EvidenceRepository } from "./packages/runtime/src/storage/repositories/EvidenceRepository.js";
|
||
import { WorkspaceRepository } from "./packages/runtime/src/storage/repositories/WorkspaceRepository.js";
|
||
import { SummaryRepository } from "./packages/runtime/src/storage/repositories/SummaryRepository.js";
|
||
import { mkdirSync, existsSync, rmSync } from "fs";
|
||
import { join } from "path";
|
||
|
||
const TEST_DIR = "/tmp/h/aircoding-diag3";
|
||
const SESSION_ID = "diag_s";
|
||
const PROJECT_ID = "diag_p";
|
||
|
||
if (existsSync(TEST_DIR)) rmSync(TEST_DIR, { recursive: true });
|
||
mkdirSync(TEST_DIR, { recursive: true });
|
||
mkdirSync(join(TEST_DIR, ".air", "local", "sessions", SESSION_ID), { recursive: true });
|
||
|
||
const db = new Database(join(TEST_DIR, ".air", "local", "sessions", SESSION_ID, "session.db"));
|
||
db.exec("PRAGMA journal_mode = WAL");
|
||
db.exec("PRAGMA synchronous = NORMAL");
|
||
db.exec("PRAGMA foreign_keys = OFF");
|
||
|
||
// Create schema manually (bypass MigrationRunner.query() issue)
|
||
db.exec(`CREATE TABLE IF NOT EXISTS schema_meta (key TEXT PRIMARY KEY, value TEXT NOT NULL)`);
|
||
db.exec(`CREATE TABLE IF NOT EXISTS sessions (
|
||
id TEXT PRIMARY KEY, project_id TEXT NOT NULL, project_root TEXT NOT NULL, title TEXT,
|
||
status TEXT NOT NULL, created_at TEXT NOT NULL, updated_at TEXT NOT NULL,
|
||
exited_at TEXT, model_provider_id TEXT, model_id TEXT, metadata_json TEXT
|
||
)`);
|
||
db.exec(`CREATE TABLE IF NOT EXISTS messages (
|
||
id TEXT PRIMARY KEY, session_id TEXT NOT NULL, role TEXT NOT NULL,
|
||
canonical_format TEXT NOT NULL, content_json TEXT NOT NULL,
|
||
parent_message_id TEXT, route_json TEXT, created_at TEXT NOT NULL,
|
||
token_estimate INTEGER, metadata_json TEXT
|
||
)`);
|
||
db.exec(`CREATE TABLE IF NOT EXISTS message_drafts (
|
||
message_id TEXT PRIMARY KEY, session_id TEXT NOT NULL, role TEXT NOT NULL,
|
||
canonical_format TEXT NOT NULL, partial_content_json TEXT NOT NULL,
|
||
status TEXT NOT NULL, created_at TEXT NOT NULL, updated_at TEXT NOT NULL, metadata_json TEXT
|
||
)`);
|
||
db.exec(`CREATE TABLE IF NOT EXISTS events (
|
||
id TEXT PRIMARY KEY, session_id TEXT NOT NULL, type TEXT NOT NULL, version INTEGER NOT NULL,
|
||
timestamp TEXT NOT NULL, source_kind TEXT NOT NULL, source_id TEXT, agent_type TEXT,
|
||
task_id TEXT, agent_id TEXT, tool_run_id TEXT, command_run_id TEXT,
|
||
route_json TEXT NOT NULL, route_text TEXT NOT NULL, payload_json TEXT NOT NULL
|
||
)`);
|
||
db.exec(`CREATE TABLE IF NOT EXISTS tasks (
|
||
id TEXT PRIMARY KEY, session_id TEXT NOT NULL, type TEXT NOT NULL, status TEXT NOT NULL,
|
||
title TEXT NOT NULL, depends_on TEXT, task_spec_json TEXT NOT NULL, worker_result_json TEXT,
|
||
assigned_agent_id TEXT, workspace_id TEXT, retry_count INTEGER NOT NULL DEFAULT 0,
|
||
created_at TEXT NOT NULL, started_at TEXT, completed_at TEXT, heartbeat_at TEXT, metadata_json TEXT
|
||
)`);
|
||
db.exec(`CREATE TABLE IF NOT EXISTS task_dependencies (
|
||
id TEXT PRIMARY KEY, session_id TEXT NOT NULL, task_id TEXT NOT NULL,
|
||
depends_on_task_id TEXT NOT NULL, dependency_type TEXT NOT NULL,
|
||
reason TEXT, created_at TEXT NOT NULL
|
||
)`);
|
||
db.exec(`CREATE TABLE IF NOT EXISTS task_attempts (
|
||
id TEXT PRIMARY KEY, session_id TEXT NOT NULL, task_id TEXT NOT NULL,
|
||
attempt_index INTEGER NOT NULL, agent_id TEXT, status TEXT NOT NULL,
|
||
worker_result_json TEXT, failure_summary TEXT, evidence_refs_json TEXT,
|
||
started_at TEXT NOT NULL, completed_at TEXT, debug_record_id TEXT
|
||
)`);
|
||
db.exec(`CREATE TABLE IF NOT EXISTS agents (
|
||
id TEXT PRIMARY KEY, session_id TEXT NOT NULL, type TEXT NOT NULL, status TEXT NOT NULL,
|
||
pid INTEGER, task_id TEXT, model_provider_id TEXT, model_id TEXT,
|
||
workspace_id TEXT, started_at TEXT NOT NULL, completed_at TEXT, heartbeat_at TEXT,
|
||
last_heartbeat_at TEXT, metadata_json TEXT
|
||
)`);
|
||
db.exec(`CREATE TABLE IF NOT EXISTS tool_runs (
|
||
id TEXT PRIMARY KEY, session_id TEXT NOT NULL, task_id TEXT, agent_id TEXT,
|
||
origin_message_id TEXT, tool_name TEXT NOT NULL, status TEXT NOT NULL,
|
||
input_json TEXT NOT NULL, output_json TEXT, error_json TEXT,
|
||
started_at TEXT NOT NULL, completed_at TEXT, duration_ms INTEGER,
|
||
artifacts_json TEXT, evidence_refs_json TEXT, metadata_json TEXT
|
||
)`);
|
||
db.exec(`CREATE TABLE IF NOT EXISTS command_runs (
|
||
id TEXT PRIMARY KEY, session_id TEXT NOT NULL, task_id TEXT, agent_id TEXT,
|
||
origin_message_id TEXT, tool_run_id TEXT,
|
||
command TEXT NOT NULL, cwd TEXT NOT NULL, exit_code INTEGER, duration_ms INTEGER,
|
||
stdout_artifact_id TEXT, stderr_artifact_id TEXT, combined_artifact_id TEXT,
|
||
diagnostic_ids TEXT, parsed_diagnostics_json TEXT,
|
||
started_at TEXT NOT NULL, completed_at TEXT, metadata_json TEXT
|
||
)`);
|
||
db.exec(`CREATE TABLE IF NOT EXISTS artifacts (
|
||
id TEXT PRIMARY KEY, session_id TEXT NOT NULL, type TEXT NOT NULL,
|
||
uri TEXT NOT NULL, path TEXT NOT NULL, original_name TEXT, size_bytes INTEGER,
|
||
sha256 TEXT, task_id TEXT, agent_id TEXT, tool_run_id TEXT, command_run_id TEXT,
|
||
associated_entity_type TEXT, associated_entity_id TEXT,
|
||
created_at TEXT NOT NULL, metadata_json TEXT
|
||
)`);
|
||
db.exec(`CREATE TABLE IF NOT EXISTS diagnostics (
|
||
id TEXT PRIMARY KEY, session_id TEXT NOT NULL, task_id TEXT, agent_id TEXT,
|
||
command_run_id TEXT, artifact_id TEXT,
|
||
language TEXT, toolchain TEXT, severity TEXT,
|
||
file TEXT, line INTEGER, column INTEGER, code TEXT,
|
||
message TEXT NOT NULL, semantic_signature TEXT NOT NULL,
|
||
created_at TEXT NOT NULL, metadata_json TEXT
|
||
)`);
|
||
db.exec(`CREATE TABLE IF NOT EXISTS evidence_refs (
|
||
id TEXT PRIMARY KEY, session_id TEXT NOT NULL, task_id TEXT, agent_id TEXT,
|
||
tool_run_id TEXT, command_run_id TEXT, artifact_id TEXT, diagnostic_id TEXT, message_id TEXT,
|
||
kind TEXT NOT NULL, ref TEXT NOT NULL, location_json TEXT, claim TEXT NOT NULL,
|
||
created_at TEXT NOT NULL
|
||
)`);
|
||
db.exec(`CREATE TABLE IF NOT EXISTS workspaces (
|
||
id TEXT PRIMARY KEY, session_id TEXT NOT NULL, task_id TEXT, agent_id TEXT,
|
||
path TEXT NOT NULL, strategy TEXT NOT NULL, status TEXT NOT NULL,
|
||
base_ref TEXT, branch_name TEXT, merged_ref TEXT, diff_artifact_id TEXT,
|
||
created_at TEXT NOT NULL, merged_at TEXT
|
||
)`);
|
||
db.exec(`CREATE TABLE IF NOT EXISTS summaries (
|
||
id TEXT PRIMARY KEY, session_id TEXT NOT NULL, type TEXT NOT NULL,
|
||
range_start_message_id TEXT, range_end_message_id TEXT,
|
||
content_json TEXT NOT NULL, created_at TEXT NOT NULL, metadata_json TEXT
|
||
)`);
|
||
db.exec(`CREATE TABLE IF NOT EXISTS ui_state (
|
||
id TEXT PRIMARY KEY, session_id TEXT NOT NULL, scope TEXT, key TEXT,
|
||
value_json TEXT, updated_at TEXT
|
||
)`);
|
||
|
||
// Repos
|
||
const repos = {
|
||
sessionRepo: new SessionRepository(db),
|
||
messageRepo: new MessageRepository(db),
|
||
messageDraftRepo: new MessageDraftRepository(db),
|
||
taskRepo: new TaskRepository(db),
|
||
taskDepRepo: new TaskDependencyRepository(db),
|
||
taskAttemptRepo: new TaskAttemptRepository(db),
|
||
agentRepo: new AgentRepository(db),
|
||
toolRunRepo: new ToolRunRepository(db),
|
||
commandRunRepo: new CommandRunRepository(db),
|
||
artifactRepo: new ArtifactRepository(db),
|
||
diagnosticRepo: new DiagnosticRepository(db),
|
||
evidenceRepo: new EvidenceRepository(db),
|
||
workspaceRepo: new WorkspaceRepository(db),
|
||
summaryRepo: new SummaryRepository(db),
|
||
};
|
||
const txManager = {
|
||
async transaction<T>(fn: (tx: any) => Promise<T>): Promise<T> {
|
||
db.exec("BEGIN"); try { const r = await fn(db); db.exec("COMMIT"); return r; } catch (e) { db.exec("ROLLBACK"); throw e; }
|
||
}
|
||
};
|
||
const eventStore = new EventStore({ db, repos, txManager });
|
||
const SID = SESSION_ID, PID = PROJECT_ID, NOW = "2026-06-11T00:00:00.000Z";
|
||
|
||
// Seed session
|
||
await eventStore.append({ id: "evt_s", type: "session.created", version: 1, session_id: SID, project_id: PID, timestamp: NOW, source: { kind: "system" }, route: ["diag"], payload: { session_id: SID, project_id: PID, project_root: TEST_DIR, title: "Diag", model_provider_id: "x", model_id: "x", metadata: {} } });
|
||
|
||
// Payload map
|
||
const P: Record<string, any> = {
|
||
"session.created": { session_id: SID, project_id: PID, project_root: TEST_DIR, title: "t", model_provider_id: "x", model_id: "x", metadata: {} },
|
||
"session.archived": { session_id: SID, reason: "t" },
|
||
"session.deleted": { session_id: SID, reason: "t" },
|
||
"user.message.created": { message_id: "m1", canonical_format: "anthropic", content_json: { text: "hi" }, token_estimate: 10, metadata: {} },
|
||
"assistant.message.started": { message_id: "m2", canonical_format: "anthropic", content_json: {}, parent_message_id: "m1", metadata: {} },
|
||
"assistant.message.created": { message_id: "m3", canonical_format: "anthropic", content_json: { text: "r" }, parent_message_id: "m2", route: [], token_estimate: 15, metadata: {} },
|
||
"assistant.message.failed": { message_id: "m3", partial_content_json: {}, error: {}, evidence_refs: [], metadata: {} },
|
||
"agent.started": { agent_id: "a1", agent_type: "executor", task_id: "t1", pid: 123, model_provider_id: "x", model_id: "x", workspace_id: "w1", metadata: {} },
|
||
"agent.completed": { agent_id: "a1", task_id: "t1", summary: "done", worker_result_ref: "r1", metadata: {} },
|
||
"agent.failed": { agent_id: "a1", task_id: "t1", error: { message: "f" }, evidence_refs: [], metadata: {} },
|
||
"agent.lost": { agent_id: "a1", task_id: "t1", last_heartbeat_at: NOW, detection_reason: "t" },
|
||
"agent.cancelled": { agent_id: "a1", task_id: "t1", reason: "t" },
|
||
"task.created": { task_id: "t1", type: "execute", title: "Test", task_spec_json: { desc: "t" }, dependencies: [], metadata: {} },
|
||
"task.started": { task_id: "t1", agent_id: "a1", attempt_id: "at1", attempt_index: 0, workspace_id: "w1" },
|
||
"task.completed": { task_id: "t1", agent_id: "a1", attempt_id: "at1", worker_result_json: {}, summary: "done", changed_files: [], evidence_refs: [] },
|
||
"task.blocked": { task_id: "t1", agent_id: "a1", reason: "b", blocker_kind: "dep", evidence_refs: [], suggested_next_step: "fix" },
|
||
"task.failed": { task_id: "t1", agent_id: "a1", attempt_id: "at1", error: { message: "f" }, evidence_refs: [], metadata: {} },
|
||
"task.cancelled": { task_id: "t1", reason: "t", cancelled_by: "user" },
|
||
"task.interrupted": { task_id: "t1", reason: "t", resumable: true, resume_ref: "r" },
|
||
"task.invalidated": { task_id: "t1", adr_id: "adr1", reason: "t", rollback_ref: "r1" },
|
||
"task.removed": { task_id: "t1", reason: "t", removed_by: "user" },
|
||
"task.debug_requested": { task_id: "t1", reason: "dbg" },
|
||
"tool.started": { tool_run_id: "tr1", tool_name: "fs.read", task_id: "t1", agent_id: "a1", origin_message_id: "m1", input_json: { path: "f" }, metadata: {} },
|
||
"tool.completed": { tool_run_id: "tr1", output_json: { r: "ok" }, duration_ms: 100, artifact_ids: [], evidence_refs: [], metadata: {} },
|
||
"tool.failed": { tool_run_id: "tr1", duration_ms: 50, error: { message: "e" }, evidence_refs: [], metadata: {} },
|
||
"tool.cancelled": { tool_run_id: "tr1", reason: "t" },
|
||
"command.started": { command_run_id: "c1", task_id: "t1", agent_id: "a1", origin_message_id: "m1", tool_run_id: "tr1", command: "echo hi", cwd: TEST_DIR, metadata: {} },
|
||
"command.completed": { command_run_id: "c1", exit_code: 0, duration_ms: 10, stdout_artifact_id: "art1", stderr_artifact_id: "art2", combined_artifact_id: "art3", diagnostic_ids: [], parsed_diagnostics_json: {}, metadata: {} },
|
||
"command.failed": { command_run_id: "c1", exit_code: 1, duration_ms: 10, stdout_artifact_id: "art1", stderr_artifact_id: "art2", combined_artifact_id: "art3", error: { message: "e" }, evidence_refs: [], metadata: {} },
|
||
"artifact.created": { artifact_id: "art1", type: "log", uri: "file:///x", path: "/x", original_name: "x.log", size_bytes: 100, sha256: "abc", task_id: "t1", agent_id: "a1", tool_run_id: "tr1", command_run_id: "c1", associated_entity_type: "task", associated_entity_id: "t1", metadata: {} },
|
||
"diagnostic.created": { diagnostic_id: "d1", task_id: "t1", agent_id: "a1", command_run_id: "c1", artifact_id: "art1", language: "cpp", toolchain: "gcc", severity: "error", file: "f.cpp", line: 1, column: 0, code: "E01", message: "err", semantic_signature: "test/e", metadata: {} },
|
||
"evidence.created": { evidence_ref_id: "ev1", kind: "build_output", ref: "r1", location_json: {}, claim: "test", task_id: "t1", agent_id: "a1", tool_run_id: "tr1", command_run_id: "c1", artifact_id: "art1", diagnostic_id: "d1", message_id: "m1" },
|
||
"context.compaction.requested": { compaction_id: "co1", title: "Compaction", task_spec_json: { reason: "b" }, reason: "budget", range_start_message_id: "m1", range_end_message_id: "m3", target_budget_tokens: 100000 },
|
||
"context.compaction.started": { compaction_id: "co1", task_id: "t1", agent_id: "a1", range_start_message_id: "m1", range_end_message_id: "m3" },
|
||
"context.compaction.completed": { compaction_id: "co1", task_id: "t1", agent_id: "a1", summary_id: "s1", range_start_message_id: "m1", range_end_message_id: "m3", token_estimate_before: 100000, token_estimate_after: 30000 },
|
||
"context.compaction.failed": { compaction_id: "co1", task_id: "t1", agent_id: "a1", range_start_message_id: "m1", range_end_message_id: "m3", error: { message: "e" }, evidence_refs: [], metadata: {} },
|
||
"summary.created": { summary_id: "s1", type: "compaction", range_start_message_id: "m1", range_end_message_id: "m3", content_json: {}, metadata: {} },
|
||
"permission.decision.recorded": { decision_id: "dec1", subject: "fs.write", action: "allow", grant_scope: "task", reason: "t", risk_level: "low", decided_by: "user", scope_json: {}, expires_at: "" },
|
||
"permission.prompt.requested": { prompt_id: "pp1", subject: "fs.write", risk_level: "low", reason: "t", options: ["allow", "deny"], default_option: "deny", request_ref: {} },
|
||
"permission.prompt.resolved": { prompt_id: "pp1", selected_option: "allow", decision_id: "dec1", resolved_by: "user" },
|
||
"doctor.run.started": { run_id: "dr1", mode: "read_only", trigger: "startup", check_type: "platform" },
|
||
"doctor.issue.found": { run_id: "dr1", issue_id: "iss1", severity: "warning", capability: "bun", dependency: "none", message: "test", fix_available: false, fix_requires_confirmation: false },
|
||
"doctor.fix.started": { run_id: "dr1", issue_id: "iss1", fix_id: "f1", strategy: "auto", fix_type: "install" },
|
||
"doctor.fix.completed": { run_id: "dr1", issue_id: "iss1", fix_id: "f1", evidence_refs: [], fix_type: "install" },
|
||
"doctor.fix.failed": { run_id: "dr1", issue_id: "iss1", fix_id: "f1", error: "fail", evidence_refs: [], metadata: {} },
|
||
"doctor.run.completed": { run_id: "dr1", status: "ok", issue_count: 0, blocking_issue_count: 0, report_artifact_id: "art1" },
|
||
"requirement.changed": { change_id: "ch1", origin_message_id: "m1", summary: "c", change_type: "update", affected_refs: ["fr1"] },
|
||
"architecture.plan.updated": { plan_ref: "p1", update_kind: "update", summary: "u", affected_task_ids: [], adr_refs: [], c4_refs: [] },
|
||
"architecture.impact.completed": { assessment_id: "as1", requirement_change_id: "ch1", impact_level: "low", decision: "continue", summary: "ok", affected_task_ids: [], evidence_refs: [] },
|
||
"workspace.created": { workspace_id: "w1", task_id: "t1", agent_id: "a1", path: "/tmp/w1", strategy: "main", base_ref: "main", branch_name: "main" },
|
||
"workspace.merge.started": { workspace_id: "w1", task_id: "t1", strategy: "main", target_ref: "main" },
|
||
"workspace.merge.completed": { workspace_id: "w1", task_id: "t1", merged_ref: "abc", diff_artifact_id: "art1" },
|
||
"workspace.merge.conflicted": { workspace_id: "w1", task_id: "t1", conflict_files: ["a.txt"], conflict_artifact_id: "art1", suggested_resolution: "merge" },
|
||
"workspace.cleaned": { workspace_id: "w1", reason: "done" },
|
||
"memory.candidate.created": { candidate_id: "m1", source_ref: {}, memory_type: "project_rule", summary: "rule", evidence_refs: [] },
|
||
"memory.promoted": { candidate_id: "m1", target_ref: "rules.md", promoted_by: "user", summary: "promoted" },
|
||
"memory.archived": { candidate_id: "m1", memory_ref: "ref", reason: "stale" },
|
||
"debug.record.created": { debug_record_id: "dbg1", task_id: "t1", failure_signature: "sig", summary: "debug", evidence_refs: [], verification_refs: [] },
|
||
};
|
||
|
||
const allEvents = new EventSchemaRegistry().list().filter(e => e.persistence === 'durable');
|
||
let pass = 0, fail = 0, cid = 0;
|
||
for (const ev of allEvents) {
|
||
const payload = P[ev.type] || {};
|
||
cid++;
|
||
try {
|
||
await eventStore.append({
|
||
id: `diag_${cid}`, type: ev.type, version: ev.version,
|
||
session_id: SID, project_id: PID,
|
||
timestamp: NOW, source: { kind: "system" }, route: ["diag"],
|
||
payload,
|
||
});
|
||
pass++;
|
||
} catch (e: any) {
|
||
fail++;
|
||
const msg = e.message || String(e);
|
||
console.log(`FAIL ${ev.type}: ${msg.split('\n')[0]}`);
|
||
}
|
||
}
|
||
|
||
console.log(`\n${pass}/${allEvents.length} passed, ${fail} failed`);
|
||
db.close();
|