lakehouse/bot/types.ts
profit f44b6b3e6b Control-plane pivot: Phase 38-44 plan + bot scaffold
Direction shift 2026-04-22: docs/CONTROL_PLANE_PRD.md becomes the
long-horizon architecture target. Existing Lakehouse (docs/PRD.md,
Phases 0-37) is preserved as the reference implementation and first
consumer. New 6-layer architecture:

  L1 Universal API /v1/chat /v1/usage /v1/sessions /v1/tools /v1/context
  L2 Routing & Policy Engine (rules, fallback chains, cost gating)
  L3 Provider Adapter Layer (Ollama + OpenRouter + Gemini + Claude)
  L4 Knowledge + Memory + Playbooks (already built)
  L5 Execution Loop (scenarios + bot/cycle.ts instances)
  L6 Observability + token accounting

Phases 38-44 sequenced with detailed per-phase specs in the PRD.
Current scope: staffing domain (synthetic workers_500k, contracts,
emails, SMS, playbooks). DevOps (Terraform/Ansible) is long-horizon
target — architecture-compatible but not current.

Files added:
- docs/CONTROL_PLANE_PRD.md — 6-layer architecture, Phase 38-44
  sequencing with staffing-first Truth Layer + Validation pipeline
- bot/ — manual-only PR bot scaffold. First consumer test-bed for
  /v1/chat (Phase 38). Mem0-aligned ADD/UPDATE/NOOP apply semantics;
  KB feedback loop reads prior cycles on same gap and injects into
  cloud prompt so bot cycles compound like scenario.ts runs do.
- tests/multi-agent/run_stress.ts — the 6-task diverse stress test
  referenced in the previous commit but missing from its staging

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 02:43:31 -05:00

89 lines
2.5 KiB
TypeScript

// Shared types for the PR-bot. Small and explicit — the bot's behavior
// should be readable from these shapes alone.
export interface Gap {
id: string; // hash of prd_line — stable key for dedup
prd_line: string; // the [bot-eligible]-tagged line, verbatim
context: string; // surrounding context from the PRD (next ~5 lines)
source_file: string; // e.g. "docs/PRD.md"
line_number: number;
}
export interface ProposalFile {
path: string; // repo-relative (no leading slash)
content: string; // full file content — the bot writes whole files, not patches
is_new: boolean; // true = create, false = overwrite existing
}
export interface Proposal {
summary: string; // one-line
rationale: string; // why this change addresses the gap
files: ProposalFile[];
estimated_loc: number; // total added+changed lines across all files
model_used: string;
tokens_used: number;
}
export interface CycleContext {
startedAt: string; // ISO
dailyCallsUsed: number;
dailyCallsBudget: number;
dailyTokensUsed: number;
dailyTokensBudget: number;
lastCycleAt: string | null;
lastCycleGapId: string | null;
autotuneBusy: boolean;
workingTreeDirty: boolean;
}
export type CycleOutcome =
| "ok" // PR opened
| "skipped_pause"
| "skipped_cost"
| "skipped_policy"
| "skipped_no_gap"
| "skipped_dirty_tree"
| "proposal_rejected"
| "apply_failed"
| "cycle_noop" // proposal applied but every file was identical to what's on disk
| "tests_failed"
| "pr_skipped_by_policy"
| "pr_failed"
| "model_failed";
// Mem0-aligned apply outcomes. Three shapes instead of the binary
// "written" / "errored". NOOP is a first-class outcome — identical
// content shouldn't waste test cycles or open an empty PR.
export type ApplyMode = "add" | "update" | "noop";
export interface ApplyOutcome {
added: string[];
updated: string[];
noop: string[];
errors: string[];
}
export interface CycleResult {
cycle_id: string;
started_at: string;
ended_at: string;
outcome: CycleOutcome;
reason: string;
gap: Gap | null;
proposal: Proposal | null;
filesAdded: string[];
filesUpdated: string[];
filesNoop: string[];
testsGreen: boolean | null; // null = not run
testsOutput: string;
prUrl: string | null;
tokens_used: number;
cloud_calls: number;
}
export interface CostState {
date: string; // YYYY-MM-DD UTC
calls: number;
tokens: number;
}