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>
89 lines
2.5 KiB
TypeScript
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;
|
|
}
|