-
Notifications
You must be signed in to change notification settings - Fork 498
feat: Feat/production database release planner #344
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,127 @@ | ||
| # AI Database Release Planner | ||
|
|
||
| ## Overview | ||
|
|
||
| AI Database Release Planner is a multi-agent AI system built with Lamatic AgentKit for analyzing SQL database migrations and producing a final release report. | ||
|
|
||
| The project is designed to help teams review database changes before release, with a focus on understanding the migration, assessing runtime behavior, choosing a deployment strategy, and deciding whether the release should proceed. | ||
|
|
||
| ## Problem Statement | ||
|
|
||
| SQL migration scripts can be difficult to evaluate quickly and consistently, especially when a release may affect production availability, locking behavior, rollback complexity, or data safety. | ||
|
|
||
| This project organizes that review into a structured agent pipeline so the migration can be analyzed step by step before a release decision is made. | ||
|
|
||
| ## Features | ||
|
|
||
| - Migration Understanding Agent for SQL schema analysis. | ||
| - Behavior Analysis Agent for PostgreSQL runtime behavior assessment. | ||
| - Deployment Strategy Agent for release planning recommendations. | ||
| - Release Decision Agent for approval and rollback guidance. | ||
| - Structured JSON contracts between every pipeline stage. | ||
| - Multi-agent workflow built with Lamatic AgentKit. | ||
|
|
||
| ## Architecture | ||
|
|
||
| The project is implemented as a Lamatic AgentKit workflow with a clear, sequential agent chain. | ||
|
|
||
| The system follows a sequential multi-agent architecture where each agent performs a single responsibility and appends its analysis to a structured JSON output. This separation of concerns improves maintainability, traceability, and extensibility. | ||
|
|
||
| Each agent receives the previous agent's JSON output, appends its own analysis, and passes the enriched result to the next stage. | ||
|
|
||
|  | ||
|
|
||
| Current stack information reflected in the project is: | ||
|
|
||
| - Lamatic AgentKit | ||
| - React | ||
| - TypeScript | ||
| - JSON Schema | ||
|
|
||
| ## Agent Pipeline | ||
|
|
||
| ```text | ||
| SQL Migration | ||
| ↓ | ||
| Migration Understanding Agent | ||
| ↓ | ||
| Behavior Analysis Agent | ||
| ↓ | ||
| Deployment Strategy Agent | ||
| ↓ | ||
| Release Decision & Rollback Advisor | ||
| ↓ | ||
| Final Release Report | ||
| ``` | ||
|
|
||
| ## Project Structure | ||
|
|
||
| ```text | ||
| production-database-release-planner/ | ||
| ├── apps/ | ||
| ├── assets/ | ||
| │ ├── diagrams/ | ||
| │ └── screenshots/ | ||
| ├── docs/ | ||
| ├── examples/ | ||
| │ ├── input/ | ||
| │ └── expected-output/ | ||
| ├── flows/ | ||
| ├── prompts/ | ||
| ├── schemas/ | ||
| │ ├── migration-understanding.schema.json | ||
| │ ├── behavior-analysis.schema.json | ||
| │ ├── deployment-strategy.schema.json | ||
| │ └── release-plan.schema.json | ||
| ├── lamatic.config.ts | ||
| └── README.md | ||
| ``` | ||
|
|
||
| ## Example Workflow | ||
|
|
||
| 1. Provide an SQL migration input file in examples/input/. | ||
| 2. Run the migration through the agent pipeline. | ||
| 3. Review the generated outputs and release recommendation. | ||
| 4. Compare the result with the reference output in examples/expected-output/. | ||
|
|
||
| ## Documentation | ||
|
|
||
| Available documentation: | ||
|
|
||
| - docs/architecture.md | ||
| - docs/pipeline.md | ||
| - docs/design-decisions.md | ||
| - docs/roadmap.md | ||
|
|
||
| Examples directory: | ||
|
|
||
| ```text | ||
| examples/ | ||
| ├── input/ | ||
| └── expected-output/ | ||
| ``` | ||
|
|
||
| ## Status | ||
|
|
||
| 🚧 Active Development | ||
|
|
||
| Current focus: | ||
|
|
||
| - Refining agent prompts | ||
| - Improving evaluation accuracy | ||
| - Expanding migration test cases | ||
| - Enhancing documentation | ||
|
|
||
| ## Future Work | ||
|
|
||
| - Support additional database engines beyond PostgreSQL. | ||
| - Expand migration pattern coverage. | ||
| - Improve agent evaluation accuracy. | ||
| - Add automated schema validation. | ||
| - Introduce policy-based release approval. | ||
| - Support additional database engines (MySQL, SQLite, SQL Server). | ||
| - Integrate automated migration validation and policy enforcement. | ||
|
|
||
| ## License | ||
|
|
||
| MIT | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| # Copy this file to .env.local and fill in the real Lamatic values on the server. | ||
|
|
||
| # Paste the Lamatic API key from your Lamatic project settings here. | ||
| LAMATIC_API_KEY= | ||
|
|
||
| # Paste the Lamatic project ID for the deployed flow here. | ||
| LAMATIC_PROJECT_ID= | ||
|
|
||
| # Paste the Lamatic workflow/flow ID for the deployed release safety pipeline here. | ||
| LAMATIC_FLOW_ID= | ||
|
|
||
| # Paste the Lamatic-generated API URL here, for example: | ||
| # https://tiyasorganization919-tiyasproject663.lamatic.dev | ||
| LAMATIC_API_URL= | ||
|
|
||
| # Optional legacy fallback for older local setups. | ||
| # If LAMATIC_API_URL is set, it is used first. | ||
| LAMATIC_PROJECT_ENDPOINT= |
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,4 @@ | ||||||||
| node_modules/ | ||||||||
| .next/ | ||||||||
| .env.local | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/usr/bin/env bash
set -euo pipefail
git check-ignore -v \
.env \
.env.local \
.env.development.local \
.env.production.local \
.env.exampleRepository: Lamatic/AgentKit Length of output: 177 🏁 Script executed: #!/usr/bin/env bash
set -u
printf '%s\n' '--- .gitignore ---'
cat -n kits/production-database-release-planner/apps/.gitignore
printf '%s\n' '--- ignore results ---'
for path in \
kits/production-database-release-planner/apps/.env \
kits/production-database-release-planner/apps/.env.local \
kits/production-database-release-planner/apps/.env.development.local \
kits/production-database-release-planner/apps/.env.production.local \
kits/production-database-release-planner/apps/.env.example
do
if git check-ignore -v --no-index "$path"; then
:
else
printf 'NOT_IGNORED %s\n' "$path"
fi
done
printf '%s\n' '--- tracked environment files ---'
git ls-files 'kits/production-database-release-planner/apps/.env*'Repository: Lamatic/AgentKit Length of output: 791 Ignore all local environment files.
Proposed fix-.env.local
+.env*
+!.env.example📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||
| *.tsbuildinfo | ||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,28 @@ | ||||||||||||||||||||||||||||||||||||||||
| import { NextResponse } from "next/server"; | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| import { runLamaticMigrationAnalysis } from "@/lib/lamatic"; | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| export const runtime = "nodejs"; | ||||||||||||||||||||||||||||||||||||||||
| export const maxDuration = 60; | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| export async function POST(request: Request) { | ||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||
| const body = (await request.json().catch(() => null)) as { | ||||||||||||||||||||||||||||||||||||||||
| sql?: unknown; | ||||||||||||||||||||||||||||||||||||||||
| } | null; | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| const sql = typeof body?.sql === "string" ? body.sql.trim() : ""; | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| if (!sql) { | ||||||||||||||||||||||||||||||||||||||||
| return NextResponse.json({ error: "SQL is required." }, { status: 400 }); | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+14
to
+18
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win Add an upper bound on the SQL payload. The handler accepts any string length and forwards it to the Lamatic flow. A large body then costs tokens and holds the route open. Reject oversized input early. 🛡️ Proposed fix+const MAX_SQL_LENGTH = 20_000;
+
const sql = typeof body?.sql === "string" ? body.sql.trim() : "";
if (!sql) {
return NextResponse.json({ error: "SQL is required." }, { status: 400 });
}
+
+ if (sql.length > MAX_SQL_LENGTH) {
+ return NextResponse.json(
+ { error: `SQL must be ${MAX_SQL_LENGTH} characters or fewer.` },
+ { status: 413 },
+ );
+ }Place the constant at module scope. 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| const analysis = await runLamaticMigrationAnalysis(sql); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| return NextResponse.json(analysis); | ||||||||||||||||||||||||||||||||||||||||
| } catch (error) { | ||||||||||||||||||||||||||||||||||||||||
| const message = error instanceof Error ? error.message : "Migration analysis failed."; | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| return NextResponse.json({ error: message }, { status: 502 }); | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+23
to
+27
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win This handler leaks internal detail to the browser. Contain it.
🔒 Proposed fix } catch (error) {
- const message = error instanceof Error ? error.message : "Migration analysis failed.";
-
- return NextResponse.json({ error: message }, { status: 502 });
+ console.error("Migration analysis failed", error);
+
+ return NextResponse.json(
+ { error: "Migration analysis failed. Try again later." },
+ { status: 502 },
+ );
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,148 @@ | ||
| @import "tailwindcss"; | ||
|
|
||
| :root { | ||
| --bg-canvas: #f4f6fb; | ||
| --bg-canvas-soft: #eef2f8; | ||
| --bg-panel: rgba(255, 255, 255, 0.88); | ||
| --bg-panel-strong: #ffffff; | ||
| --bg-editor: #f8fafc; | ||
| --bg-editor-muted: #f1f5f9; | ||
| --border-subtle: rgba(15, 23, 42, 0.08); | ||
| --border-strong: rgba(37, 99, 235, 0.18); | ||
| --text-primary: #111827; | ||
| --text-secondary: #475569; | ||
| --text-muted: #6b7280; | ||
| --accent-blue: #2563eb; | ||
| --accent-blue-soft: #dbeafe; | ||
| --accent-green: #15803d; | ||
| --accent-amber: #c2410c; | ||
| --accent-red: #b91c1c; | ||
| --shadow-panel: 0 18px 60px rgba(15, 23, 42, 0.08); | ||
| --shadow-soft: 0 8px 24px rgba(15, 23, 42, 0.06); | ||
| } | ||
|
|
||
| *, | ||
| *::before, | ||
| *::after { | ||
| box-sizing: border-box; | ||
| } | ||
|
|
||
| html { | ||
| scroll-behavior: smooth; | ||
| } | ||
|
|
||
| body { | ||
| margin: 0; | ||
| min-height: 100vh; | ||
| background: | ||
| radial-gradient(circle at top left, rgba(96, 165, 250, 0.18), transparent 24%), | ||
| radial-gradient(circle at top right, rgba(191, 219, 254, 0.55), transparent 30%), | ||
| linear-gradient(180deg, #f8fafc 0%, #f2f5fb 42%, #edf2f8 100%); | ||
| color: var(--text-primary); | ||
| font-family: var(--font-manrope), sans-serif; | ||
| -webkit-font-smoothing: antialiased; | ||
| -moz-osx-font-smoothing: grayscale; | ||
| } | ||
|
|
||
| ::selection { | ||
| background: rgba(37, 99, 235, 0.16); | ||
| } | ||
|
|
||
| ::-webkit-scrollbar { | ||
| width: 9px; | ||
| height: 9px; | ||
| } | ||
|
|
||
| ::-webkit-scrollbar-track { | ||
| background: rgba(148, 163, 184, 0.08); | ||
| } | ||
|
|
||
| ::-webkit-scrollbar-thumb { | ||
| border-radius: 999px; | ||
| background: rgba(100, 116, 139, 0.34); | ||
| } | ||
|
|
||
| ::-webkit-scrollbar-thumb:hover { | ||
| background: rgba(100, 116, 139, 0.48); | ||
| } | ||
|
|
||
| .grid-overlay { | ||
| background-image: | ||
| linear-gradient(rgba(148, 163, 184, 0.08) 1px, transparent 1px), | ||
| linear-gradient(90deg, rgba(148, 163, 184, 0.08) 1px, transparent 1px); | ||
| background-size: 52px 52px; | ||
| mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0.18), transparent 88%); | ||
| } | ||
|
|
||
| .panel { | ||
| border: 1px solid var(--border-subtle); | ||
| background: var(--bg-panel); | ||
| backdrop-filter: blur(16px); | ||
| box-shadow: var(--shadow-panel); | ||
| } | ||
|
|
||
| .panel-strong { | ||
| border: 1px solid rgba(15, 23, 42, 0.07); | ||
| background: var(--bg-panel-strong); | ||
| box-shadow: var(--shadow-soft); | ||
| } | ||
|
|
||
| .code-font { | ||
| font-family: var(--font-ibm-plex-mono), monospace; | ||
| } | ||
|
|
||
| .soft-ring { | ||
| box-shadow: | ||
| inset 0 1px 0 rgba(255, 255, 255, 0.7), | ||
| 0 0 0 1px rgba(15, 23, 42, 0.02); | ||
| } | ||
|
|
||
| .surface-glow { | ||
| position: relative; | ||
| isolation: isolate; | ||
| } | ||
|
|
||
| .surface-glow::before { | ||
| content: ""; | ||
| position: absolute; | ||
| inset: -1px; | ||
| z-index: -1; | ||
| border-radius: inherit; | ||
| background: linear-gradient( | ||
| 135deg, | ||
| rgba(255, 255, 255, 0.95), | ||
| rgba(219, 234, 254, 0.92) 55%, | ||
| rgba(255, 255, 255, 0.72) | ||
| ); | ||
| } | ||
|
|
||
| .spin-slow { | ||
| animation: spin-slow 14s linear infinite; | ||
| } | ||
|
|
||
| @keyframes spin-slow { | ||
| from { | ||
| transform: rotate(0deg); | ||
| } | ||
|
|
||
| to { | ||
| transform: rotate(360deg); | ||
| } | ||
| } | ||
|
|
||
| @keyframes pulse-signal { | ||
| 0%, | ||
| 100% { | ||
| opacity: 0.5; | ||
| transform: scale(1); | ||
| } | ||
|
|
||
| 50% { | ||
| opacity: 1; | ||
| transform: scale(1.08); | ||
| } | ||
| } | ||
|
|
||
| .pulse-signal { | ||
| animation: pulse-signal 1.8s ease-in-out infinite; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| import type { Metadata } from "next"; | ||
| import { IBM_Plex_Mono, Manrope } from "next/font/google"; | ||
| import "./globals.css"; | ||
|
|
||
| const manrope = Manrope({ | ||
| subsets: ["latin"], | ||
| variable: "--font-manrope", | ||
| }); | ||
|
|
||
| const ibmPlexMono = IBM_Plex_Mono({ | ||
| subsets: ["latin"], | ||
| variable: "--font-ibm-plex-mono", | ||
| weight: ["400", "500"], | ||
| }); | ||
|
|
||
| export const metadata: Metadata = { | ||
| title: "Production Database Release Planner | Lamatic AgentKit", | ||
| description: | ||
| "Frontend workspace for staging SQL migration input before Lamatic AgentKit release safety analysis.", | ||
| }; | ||
|
|
||
| export default function RootLayout({ | ||
| children, | ||
| }: Readonly<{ children: React.ReactNode }>) { | ||
| return ( | ||
| <html lang="en"> | ||
| <body className={`${manrope.variable} ${ibmPlexMono.variable}`}> | ||
| {children} | ||
| </body> | ||
| </html> | ||
| ); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Add a complete setup guide.
Document prerequisites, how to copy
apps/.env.exampleto.env.localand configure the required Lamatic variables, how to work from theapps/directory, and how to install dependencies and run the app withnpm ciandnpm run dev. Include the setup steps in a dedicated## Setupsection so users can run the kit from a fresh checkout.📍 Affects 1 file
kits/production-database-release-planner/README.md#L1-L7(this comment)kits/production-database-release-planner/README.md#L32-L32🤖 Prompt for AI Agents
Source: Coding guidelines