/** * Izanagi AI Runtime — Tipos compartilhados * * Núcleo tipado do Adaptive Agent & Skill Runtime: evaluation, execution graph, * routing, memória de falhas, self-healing, tracing e contratos. * * Nenhuma dependência externa. Todos os módulos do runtime consomem estes tipos. */ import type { ExecutionMode } from './contracts/task-contract.js'; export type Verdict = 'PASS' | 'PASS_WITH_WARNINGS' | 'FAIL' | 'BLOCKED' | 'UNKNOWN'; export type MetricName = 'correctness' | 'requirementCoverage' | 'testResults' | 'architecture' | 'security' | 'performance' | 'maintainability' | 'confidence' | 'cost' | 'latency' | 'artifactValidity'; export type Metrics = Partial>; export interface TestSummary { passed: number; failed: number; skipped?: number; total?: number; durationMs?: number; failures?: Array<{ name: string; message: string; file?: string; }>; } export interface EvaluationResult { /** Verdict computado pelos thresholds. */ verdict: Verdict; /** Score global ponderado em [0,1]. */ score: number; /** Confiança da avaliação em [0,1]. */ confidence: number; metrics: Metrics; tests?: TestSummary; regressions: string[]; recommendations: string[]; /** Thresholds usados para derivar o verdict. */ thresholds?: EvaluationThresholds; } export interface EvaluationThresholds { pass: number; passWithWarnings: number; } export interface EvaluationReport extends EvaluationResult { taskId: string; task: string; agentId?: string; createdAt: string; durationMs?: number; artifacts?: ArtifactRef[]; weightings?: MetricWeightings; } export interface MetricWeightings { correctness: number; requirementCoverage: number; testResults: number; architecture: number; security: number; performance: number; maintainability: number; artifactValidity: number; } export type ArtifactKind = 'requirements' | 'architecture' | 'database-schema' | 'api-contract' | 'security-report' | 'test-plan' | 'implementation-plan' | 'evaluation' | 'benchmark-report' | 'research' | 'trace' | 'critique' | 'delivery' | 'project-survey' | 'materialization' | 'test-run' | 'raw'; export interface ArtifactRef { kind: ArtifactKind; path?: string; name: string; /** Tamanho em bytes (0 quando não materializado). */ size?: number; /** Hash simples do conteúdo para detecção de duplicação. */ hash?: string; valid?: boolean; issues?: string[]; /** * Proveniência — preenchida quando o artefato passou pelo `ArtifactRegistry` * (`runtime/artifacts/registry.ts`); ausente para artefatos construídos * soltos via `makeArtifact()` antes de qualquer registro (ex.: benchmarks). */ id?: string; /** Quem produziu — agente e/ou skill responsável (formato livre, ex. "senior-engineer/tdd"). */ producer?: string; createdAt?: string; status?: 'valid' | 'invalid'; } /** Schema mínimo de um artefato — usado pelo validators.ts. */ export interface ArtifactSchema { kind: ArtifactKind; /** Campos obrigatórios do artefato. */ required: string[]; /** Validações por campo: [campo, regex, mensagem]. */ patterns?: Array<[string, RegExp, string]>; /** Tamanho mínimo de conteúdo (bytes). */ minSize?: number; /** Proibido: strings que indicam stub/lazy code. */ forbidden?: string[]; /** Validação custom (assinatura simples de função). */ validate?: (content: unknown) => string[]; /** * Trecho que a SIMULAÇÃO headless precisa conter para satisfazer `validate`. * Só existe em schema com validação custom: os campos de `required` já são * derivados automaticamente. Mora aqui, junto do schema, porque schema e * simulação divergirem em silêncio é exatamente o bug que isto evita. */ simulationHint?: string; /** * Conteúdo CAPTURADO de uma execução, não escrito por um agente. * * Desliga a varredura anti-stub (`TODO`, `FIXME`, `placeholder`...), que * pressupõe texto autoral. O caso que revelou isso: a saída do runner de * testes do Node imprime `ℹ todo 0` no resumo, e o artefato `test-run` de uma * suíte 100% VERDE era reprovado por "stub detectado". A varredura estava * medindo o vocabulário de um relatório de execução, e o efeito era reprovar * a evidência justamente quando ela era boa. */ capturedOutput?: boolean; } export type NodeStatus = 'pending' | 'running' | 'succeeded' | 'failed' | 'skipped' | 'retrying' | 'blocked'; export type RetryPolicy = { maxAttempts: number; backoffMs: number; /** Multiplicador de backoff a cada tentativa. */ backoffFactor?: number; /** Se true, falha de validação de artefato conta como retryable. */ retryOnValidation?: boolean; }; export interface GraphNode { id: string; kind: 'agent' | 'skill' | 'tool' | 'validator' | 'evaluator' | 'aggregator' | 'parallel' | 'gate' | 'approval'; agent?: string; skills?: string[]; inputs?: string[]; outputs?: string[]; /** Ids de nós que devem concluir antes deste. */ dependencies?: string[]; /** Condição de execução (expressão JS simples sobre o estado). */ condition?: string; retryPolicy?: RetryPolicy; timeoutMs?: number; tokenBudget?: number; validator?: string; status?: NodeStatus; attempts?: number; artifacts?: ArtifactRef[]; error?: string; startedAt?: string; endedAt?: string; durationMs?: number; model?: string; metadata?: Record; } export interface ExecutionGraph { id: string; task: string; createdAt: string; nodes: GraphNode[]; /** Topological order computada pelo planner. */ order: string[]; /** Etapas paralelas detectadas: grupos de ids executáveis juntos. */ parallelBatches: string[][]; /** Orçamento global. */ budget: { maxAttempts: number; maxTokens: number; maxTimeMs: number; }; } /** * Stacks de destino de um agente/skill gerado. `all` = indiferente a stack * (default): o artefato vale para qualquer projeto. As demais marcam que o * artefato nasceu com capacidades, guardrails e validação daquela stack — * ex.: um agente `stack: 'rust'` exige `cargo clippy + cargo test` na entrega. */ export declare const STACKS: readonly ["ts", "go", "rust", "python", "all"]; export type Stack = (typeof STACKS)[number]; export interface CandidateScore { candidate: string; relevance: number; historicalSuccess: number; compatibility: number; risk: number; cost: number; latency: number; finalScore: number; reasons: string[]; } export interface AgentGenome { name: string; version: string; purpose: string; capabilities: string[]; requiredSkills: string[]; optionalSkills: string[]; inputs: string[]; outputs: string[]; constraints: string[]; permissions: string[]; handoffs: Array<{ to: string; reason: string; }>; memory: string[]; evaluation: { metrics: MetricName[]; minScore: number; }; tokenBudget: number; compatibility: string; model?: string; /** Stacks de destino (default `['all']`). Ver `STACKS`. */ stacks?: Stack[]; /** Campos legacy preservados (compatibilidade). */ role?: string; identity?: string; skills?: string[]; chains?: Record; always?: string[]; never?: string[]; } /** * Ciclo de vida de uma skill. Skills curadas do framework nascem `active`; * skills geradas pela Skill Factory nascem `draft` (passaram no security * scan mas ainda não têm histórico de uso real) — nunca "Generate → * Automatically trust". */ export type SkillLifecycle = 'discovered' | 'draft' | 'validated' | 'active' | 'deprecated' | 'archived'; export interface SkillManifest { name: string; version: string; description: string; /** Default 'active' (skills curadas pré-existentes) quando não declarado no frontmatter. */ lifecycle?: SkillLifecycle; capabilities: string[]; triggers: string[]; dependencies: string[]; inputs: string[]; outputs: string[]; permissions: string[]; compatibility: string; risk: 'low' | 'medium' | 'high'; tokenBudget: number; evaluation?: { metrics: MetricName[]; minScore?: number; }; examples?: string[]; changelog?: Array<{ version: string; date?: string; change: string; }>; /** Stacks de destino da skill (default `all` quando ausente). Ver `STACKS`. */ stacks?: Stack[]; /** Conteúdo cru do SKILL.md (sem frontmatter). */ body?: string; path?: string; } export type MemoryCategory = 'episodic' | 'semantic' | 'procedural' | 'decision' | 'failure' | 'skill' | 'project'; export type FailureKind = 'recoverable' | 'non-recoverable' | 'planning' | 'tool' | 'agent' | 'validation' | 'dependency' | 'unknown'; /** * Taxonomia de ORIGEM da falha (independente de `FailureKind`, que classifica a * ESTRATÉGIA de recuperação). Existe para relatório/observabilidade — nunca * substitui `FailureKind`, que continua governando a lógica de cura em * `recovery/healing.ts`. */ export type FailureCategory = 'MODEL_FAILURE' | 'TOOL_FAILURE' | 'VALIDATION_FAILURE' | 'ARTIFACT_FAILURE' | 'TEST_FAILURE' | 'SECURITY_FAILURE' | 'TIMEOUT' | 'DEPENDENCY_FAILURE' | 'CONFIGURATION_FAILURE' | 'ENVIRONMENT_FAILURE' | 'AGENT_FAILURE' | 'UNKNOWN_FAILURE'; export interface FailurePattern { pattern: string; symptoms: string[]; rootCause: string; solution: string; confidence: number; occurrences: number; kind?: FailureKind; firstSeen?: string; lastSeen?: string; tags?: string[]; /** * Memory Lifecycle (create/retrieve/update/promote/invalidate/archive). * Ausente = 'active' (compatibilidade com padrões gravados antes deste campo existir). * 'invalidated' = a solução registrada não se aplica mais (codebase mudou, causa raiz * era outra) — para de ser sugerida por `findRelevantFailures`, mas fica no histórico. * 'archived' = decisão manual e final de não usar mais este padrão (não é reativado * automaticamente por uma nova ocorrência, ao contrário de 'invalidated'). */ status?: 'active' | 'invalidated' | 'archived'; invalidatedReason?: string; } export interface MemoryEntry { id: string; category: MemoryCategory; title: string; content: string; tags: string[]; createdAt: string; updatedAt: string; source?: string; confidence?: number; } export interface TraceSpan { id: string; name: string; type: 'task' | 'decision' | 'agent' | 'skill' | 'tool' | 'model' | 'evaluation' | 'retry' | 'healing' | 'artifact' | 'memory'; status: 'ok' | 'error' | 'skipped' | 'blocked'; startedAt: string; endedAt: string; durationMs: number; metadata?: Record; error?: string; } export interface RunTrace { runId: string; task: string; /** Desempate monotônico dentro do processo para runs com o mesmo startedAt (ms). */ seq?: number; startedAt: string; endedAt: string; durationMs: number; command: string; model?: string; tokens?: { input: number; output: number; total: number; }; retries: number; failures: number; agents: string[]; skills: string[]; tools: string[]; artifacts: ArtifactRef[]; evaluation?: EvaluationReport; healing?: HealingAction[]; spans: TraceSpan[]; graph?: ExecutionGraph; /** Token Budget 2.0 — gasto por fase (planning/execution/evaluation/recovery). */ budget?: Record; /** * Modo de execução escolhido pelo Commander (direct/assisted/orchestrated/ * autonomous). Ausente em runs planejados pelo caminho legado. */ mode?: string; /** Token Economy Engine: tokens, custo, cache, paralelismo, escaladas, degradação. */ telemetry?: Record; /** Verificação por nó (Verification Engine 2.0): VERIFIED / UNVERIFIED / FAILED. */ verification?: Array<{ nodeId: string; status: string; score: number; reason: string; unmet: string[]; }>; /** * Protocolo agente-a-agente: quem falou com quem durante o run. Carrega * referência de artefato e resumo de uma linha, nunca o conteúdo produzido * (senão o trace viraria uma segunda cópia do run inteiro). */ conversation?: Array<{ id: string; from: string; to: string; type: string; taskId: string; artifactRefs?: string[]; summary: string; confidence?: number; timestamp: string; }>; } export type HealingActionKind = 'local_repair' | 'replan' | 'handoff' | 'skill_replacement' | 'retry' | 'abort'; export interface HealingAction { id: string; kind: HealingActionKind; failureKind: FailureKind; /** Taxonomia de origem (MODEL_FAILURE, TOOL_FAILURE, ...) — ver `FailureCategory`. */ category: FailureCategory; message: string; nodeId?: string; /** Skill/agente substituto (skill_replacement / handoff). */ replacement?: string; /** Novo grafo gerado no replan. */ newGraphId?: string; matchedPattern?: string; createdAt: string; /** * Limite DECLARADO que foi esgotado, quando o abort veio de um teto e não de * uma falha irrecuperável. * * A distinção que este campo carrega: um run que esgotou o orçamento não * falhou por bug, ele chegou onde alguém disse que ele poderia chegar. Os * dois terminavam iguais (`abort` + veredito `FAIL`), e a diferença é * justamente o que decide o que fazer a seguir — subir o teto e retomar, ou * investigar. É o que promove o veredito do run a `HUMAN_REQUIRED`. */ exhausted?: ExhaustedLimit; } /** Teto do runtime que um run pode esgotar. */ export type ExhaustedLimit = 'attempts' | 'time' | 'tokens' | 'cost'; export type ModelTier = 'fast' | 'balanced' | 'premium'; export interface ModelProvider { id: string; name: string; models: ModelSpec[]; /** * Data (ISO `YYYY-MM-DD`) da tabela de preços deste provider. * * Obrigatória na prática para quem cobra por token, ausente para * self-hosted: custo 0 é fato, não cotação. Existe porque preço em * código-fonte envelhece sem avisar, e `estimateCostForRole` alimenta o teto * de orçamento: preço velho é teto errado, e o teto decide degradar, * rebaixar papel ou pedir aprovação. Com a data, `izanagi models` mostra a * idade e avisa; sem ela, o framework afirmaria um número que ninguém * conferiu. Opcional no tipo para não quebrar catálogo de projeto existente. */ pricingAsOf?: string; } export interface ModelSpec { id: string; tier: ModelTier; contextWindow: number; costPer1kInput: number; costPer1kOutput: number; avgLatencyMs: number; reasoning: 'low' | 'medium' | 'high'; score?: number; } export interface RoutingContext { task: string; taskComplexity: 1 | 2 | 3 | 4 | 5; reasoningRequirement: 'low' | 'medium' | 'high'; risk: number; tokenBudget: number; requiresTools: boolean; historicalPerformance?: Record; } /** * O que o roteamento por no' so' pode saber DURANTE a execucao: quanto sobrou * do orcamento e como cada modelo se comportou historicamente. Opcional de * proposito: quem roteia fora de um run (o juiz semantico, a estimativa de * custo do plano) nao tem nem um nem outro, e ausencia aqui e' ausencia de * sinal, nao sinal ruim. */ export interface RoutingHints { /** Saldo do teto de tokens do run (`ExecutionBudget.remainingTokens`). */ remainingTokens?: number; /** Taxa de sucesso por model id (`MemoryStore.historicalPerformance()`). */ historicalPerformance?: Record; } export type BenchmarkDomain = 'coding' | 'debugging' | 'architecture' | 'security' | 'database' | 'frontend' | 'backend' | 'automation' | 'research' | 'refactoring'; export interface BenchmarkCase { id: string; domain: BenchmarkDomain; task: string; requirements: string[]; expectedArtifacts: string[]; /** Funções de validação simples: [nome, mensagem] sobre o output. */ validators?: Array<{ name: string; message: string; check: string; }>; metrics: MetricName[]; tags: string[]; /** * Teto sob o qual o caso deve ser resolvido (`izanagi benchmark run * --execute`). Sem isto, "custo" da base oficial era observado e nunca * imposto: um caso resolvido com dez vezes o orcamento passava igual. */ budget?: { maxTokens?: number; maxCost?: number; maxTimeMs?: number; maxToolCalls?: number; maxAgents?: number; maxRetries?: number; }; /** Modo de execucao exigido pelo caso. Ausente: o Commander decide. */ mode?: ExecutionMode; /** * Tools que o caso autoriza. Ausente: sem allowlist. Lista vazia: nenhuma * tool, que e' declaracao e nao ausencia. */ allowedTools?: string[]; } export interface BenchmarkResult { caseId: string; domain: BenchmarkDomain; passed: boolean; score: number; artifactsFound: string[]; artifactsMissing: string[]; validatorFailures: string[]; metrics: Metrics; durationMs: number; tokensUsed?: number; /** * Evidência de uma execução REAL deste caso (verificação, recuperação, * retries, custo). Ausente quando o caso foi avaliado só pelo output * esperado — e a ausência é informação: significa que o relatório não mede * verificação nem recuperação. */ execution?: import('./benchmarks/arena.js').ExecutionEvidence; /** * Métricas que o caso PEDIU e que este caminho de medição não produz. * * O caminho de output mede duas coisas de verdade: a razão de artefatos * esperados que apareceram e a latência. `correctness`, `security`, * `architecture` e as demais exigem julgar o CONTEÚDO, e antes esta lista não * existia porque todas recebiam o mesmo número da razão de artefatos: o * relatório salvo mostrava cinco medidas independentes que eram uma medida * repetida cinco vezes. */ metricsNotMeasured?: MetricName[]; /** * Teto efetivamente aplicado nesta execução. Ausente quando o caso não * declarou orçamento, e a ausência é o que torna dois relatórios * comparáveis ou não. */ budgetApplied?: { maxTokens?: number; maxCostUsd?: number; }; /** * Checagens que o caminho de medição não mediu, e que por isso ficaram fora * da nota. Presente é informação: um score de 1.00 com * `unmeasured: ['expectedArtifacts']` diz que os validators passaram e que * ninguém conferiu arquivo nenhum. */ unmeasured?: string[]; } export interface BenchmarkReport { id: string; suite: string; version: string; createdAt: string; frameworkVersion: string; results: BenchmarkResult[]; summary: { total: number; passed: number; failed: number; avgScore: number; totalDurationMs: number; }; /** Pontuação média por domínio. */ byDomain: Record; /** * Agregado das métricas de execução real (Izanagi Arena). Presente só quando * ao menos um caso rodou pelo runtime de verdade. */ execution?: import('./benchmarks/arena.js').ExecutionSummary; } export type RiskLevel = 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL'; export interface ScanFinding { severity: RiskLevel; rule: string; message: string; line?: number; match?: string; } export interface SkillScanResult { skill: string; path: string; score: number; level: RiskLevel; findings: ScanFinding[]; scannedAt: string; /** Trust tier de origem (builtin/generated/community) — determina o bloqueio escalonado. */ trustTier?: 'builtin' | 'generated' | 'community'; /** Decisão final considerando o trust tier: 'allow' | 'warn' | 'block'. */ verdict?: 'allow' | 'warn' | 'block'; } export interface Handoff { from: string; to: string; reason: string; context: Record; artifacts: string[]; decisions: string[]; constraints: string[]; openQuestions: string[]; } export interface AgentStats { runs: number; successes: number; failures: number; avgScore: number; avgTokens: number; lastRunAt?: string; /** * Mesma estatística recortada por domínio técnico do run. Um agente que vai * bem em backend e mal em frontend não pode ser julgado por uma média só. * Ausente em estado gravado antes desta versão (o global continua valendo). */ byDomain?: Record; } export interface SkillStats { uses: number; successes: number; failures: number; avgScore: number; avgTokens: number; lastUsedAt?: string; } export interface ModelStats { runs: number; successes: number; failures: number; avgScore: number; avgTokens: number; lastRunAt?: string; } export interface RuntimeState { schemaVersion: number; agents: Record; skills: Record; /** * Trajetórias observadas: caminhos de execução que se repetiram. Ausente em * estado gravado antes desta versão. */ trajectories?: Record; /** Histórico de performance por modelo (ex.: "claude-sonnet-4-5") — alimenta RoutingContext.historicalPerformance. */ models: Record; failures: Record; learnings: Array<{ id: string; text: string; source: string; createdAt: string; confidence: number; }>; updatedAt: string; } //# sourceMappingURL=types.d.ts.map