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>
59 lines
1.6 KiB
TypeScript
59 lines
1.6 KiB
TypeScript
// Gitea PR open. Reads PAT from ~/.git-credentials (set up by the
|
|
// credential-helper flow). All PRs open as DRAFT so J reviews before
|
|
// merge — never auto-merge.
|
|
|
|
import { readFile } from "node:fs/promises";
|
|
|
|
const GITEA_HOST = "https://git.agentview.dev";
|
|
const REPO_OWNER = "profit";
|
|
const REPO_NAME = "lakehouse";
|
|
const CRED_FILE = "/home/profit/.git-credentials";
|
|
|
|
async function readPat(): Promise<string> {
|
|
const raw = await readFile(CRED_FILE, "utf8");
|
|
for (const line of raw.split("\n")) {
|
|
const m = line.match(/^https:\/\/[^:]+:([^@]+)@git\.agentview\.dev/);
|
|
if (m) return m[1];
|
|
}
|
|
throw new Error(`no Gitea PAT found in ${CRED_FILE}`);
|
|
}
|
|
|
|
export interface OpenPrInput {
|
|
branch: string; // head branch (just pushed)
|
|
base?: string; // default "main"
|
|
title: string;
|
|
body: string;
|
|
}
|
|
|
|
export interface OpenPrResult {
|
|
number: number;
|
|
html_url: string;
|
|
}
|
|
|
|
export async function openPr(input: OpenPrInput): Promise<OpenPrResult> {
|
|
const pat = await readPat();
|
|
const url = `${GITEA_HOST}/api/v1/repos/${REPO_OWNER}/${REPO_NAME}/pulls`;
|
|
const payload = {
|
|
title: input.title,
|
|
body: input.body,
|
|
head: input.branch,
|
|
base: input.base ?? "main",
|
|
// Gitea uses "draft" flag — always on for bot PRs.
|
|
draft: true,
|
|
};
|
|
const r = await fetch(url, {
|
|
method: "POST",
|
|
headers: {
|
|
"content-type": "application/json",
|
|
"Authorization": `token ${pat}`,
|
|
},
|
|
body: JSON.stringify(payload),
|
|
signal: AbortSignal.timeout(30000),
|
|
});
|
|
if (!r.ok) {
|
|
throw new Error(`Gitea ${r.status}: ${await r.text()}`);
|
|
}
|
|
const j = await r.json() as any;
|
|
return { number: j.number, html_url: j.html_url };
|
|
}
|