{"id":112594,"date":"2026-09-18T12:00:00","date_gmt":"2026-09-18T12:00:00","guid":{"rendered":"https:\/\/www.red-gate.com\/simple-talk\/?p=112594"},"modified":"2026-09-08T15:45:56","modified_gmt":"2026-09-08T15:45:56","slug":"what-happens-when-your-ai-coding-agent-starts-a-database-on-its-own-building-an-app-with-ai-part-six","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/ai\/what-happens-when-your-ai-coding-agent-starts-a-database-on-its-own-building-an-app-with-ai-part-six\/","title":{"rendered":"What happens when your AI coding agent starts a database on its own (building an app with AI, part six)"},"content":{"rendered":"\n<p><strong>At the end of the <a href=\"https:\/\/www.red-gate.com\/simple-talk\/ai\/ai-built-my-wordpress-plugin-heres-what-worked-and-what-went-wrong-building-an-app-with-ai-part-five\/\" target=\"_blank\" rel=\"noreferrer noopener\">previous article<\/a> in my <a href=\"https:\/\/www.red-gate.com\/simple-talk\/collections\/how-i-built-an-app-just-by-talking-to-an-ai-llm\/\" target=\"_blank\" rel=\"noreferrer noopener\">series on building an app and database almost entirely through an LLM<\/a>, there was a functional WordPress plugin accessing my PostgreSQL database sitting on Azure. It\u2019s secure (protected against SQL Injection), and roughly does what I want &#8211; but is still not <em>quite<\/em> right. <\/strong><\/p>\n\n\n\n<p><strong>So, in this &#8211; part six of the series &#8211; I&#8217;ll try to make the AI iterate some changes. Wish me luck.<\/strong><\/p>\n\n\n\n<p>Note for returning readers: I&#8217;m now using Claude, not <a href=\"https:\/\/copilot.microsoft.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Microsoft CoPilot<\/a>, in line with a recent change we made at my place of work (<a href=\"https:\/\/www.red-gate.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Redgate<\/a>).<\/p>\n\n\n\n<p>And, for new readers, here&#8217;s how I do things: I get Claude to generate a prompt, and then <a href=\"https:\/\/claude.com\/product\/claude-code\" target=\"_blank\" rel=\"noreferrer noopener\">Claude Code<\/a> does the work. As I have done in every article, I&#8217;ll be posting my prompts <em>and<\/em> the AI responses. I mark these clearly, so it&#8217;s easy to see which parts are written by me and which come from the LLM. I\u2019m writing most of this myself &#8211; promise!<\/p>\n\n\n\n<p><em>This is the sixth part of Grant Fritchey\u2019s\u00a0<a href=\"https:\/\/www.red-gate.com\/simple-talk\/collections\/how-i-built-an-app-just-by-talking-to-an-ai-llm\/\" target=\"_blank\" rel=\"noreferrer noopener\">series on building an app and database almost entirely through an LLM.<\/a>\u00a0The repo, including every prompt, lives\u00a0<a href=\"https:\/\/github.com\/ScaryDBA\/dbRosetta\" target=\"_blank\" rel=\"noreferrer noopener\">on GitHub<\/a>.<\/em><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-fixing-the-ui\">Fixing the UI<\/h2>\n\n\n\n<p>I want my app, <em>dbRosetta<\/em>, to educate you. For example, if you know that a procedure is used to return data in <a href=\"https:\/\/www.red-gate.com\/simple-talk\/databases\/sql-server\/\" target=\"_blank\" rel=\"noreferrer noopener\">SQL Server<\/a>, what\u2019s the equivalent in <a href=\"https:\/\/www.red-gate.com\/simple-talk\/databases\/oracle-databases\/\" target=\"_blank\" rel=\"noreferrer noopener\">Oracle<\/a> and <a href=\"https:\/\/www.red-gate.com\/simple-talk\/databases\/postgresql\/\" target=\"_blank\" rel=\"noreferrer noopener\">PostgreSQL<\/a>? I also want some better sample data. <\/p>\n\n\n\n<p><strong>For this, here\u2019s my prompt for Claude:<\/strong><\/p>\n\n\n\n<div id=\"callout-block_034a4748061f10d717be7c2d147626c7\" class=\"callout alignnone\">\n    <div class=\"child-last:mb-0 child-first:mt-0 bg-gray-50 dark:bg-gray-950 p-4xl my-3xl\">\n\n<p><em>I&#8217;d like you to use the <code>canonical_template.md<\/code> to create a prompt for Claude Code.<\/em><\/p>\n\n\n\n<p><em>In this case, I want to iterate on the application interface. The current state of the UI is visible here: <a href=\"https:\/\/www.scarydba.com\/dbrosetta\/\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/www.scarydba.com\/dbrosetta\/<\/a><\/em><\/p>\n\n\n\n<p><em>I want to change the input so that you define both a term, and the data platform that you already understand how that term applies. You then supply the term and the output then translates the term to one or more of the other data platforms. <\/em><\/p>\n\n\n\n<p><em>For example: &#8216;transaction log&#8217; in &#8216;SQL Server&#8217;, and I wanted to know what was the nearest equivalent in &#8216;PostgreSQL&#8217; which would be &#8216;Write Ahead Log (WAL)&#8217; as the answer. The UI has to change to allow for selecting the data platform in put. <\/em><\/p>\n\n\n\n<p><em>It also should allow multiple selections for the output, either all data platforms, or, the ability to select one or more like a drop down with check boxes or something similar.<\/em><\/p>\n\n\n\n<p><em>If necessary, we can change the data structures to meet these requirements.<\/em><\/p>\n\n\n\n<p><em>I would also like additional data to be generated. Please find 6-8 terms that are different, similar to the &#8216;transaction log&#8217; &#8216;write ahead log&#8217; example above, across PostgreSQL, MySQL, Oracle and SQL Server.<\/em><\/p>\n\n\n\n<p><em>Please generate the necessary prompt for Claude Code.<\/em><\/p>\n\n<\/div>\n<\/div> \n\n\n<p><strong>Now, Claude is generally more of a stickler for exactitude than I found with CoPilot. It generated this prompt by <em>really<\/em> closely following the template:<\/strong><\/p>\n\n\n\n<div id=\"callout-block_034a4748061f10d717be7c2d147626c7\" class=\"callout alignnone\">\n    <div class=\"child-last:mb-0 child-first:mt-0 bg-gray-50 dark:bg-gray-950 p-4xl my-3xl\">\n\n<p><em><strong>SYSTEM:<\/strong> You are a senior full-stack engineer working in the existing dbRosetta repository (Fastify + Prisma + PostgreSQL API, Flyway migrations, and a WordPress plugin front end). Make minimal, additive, well-tested changes that match the existing code style in each file you touch. Do not invent database facts; use only the seed data given to you verbatim.<\/em><\/p>\n\n\n\n<p><em><strong>USER:<\/strong> Implement a directional term-lookup feature that replaces dbRosetta&#8217;s current keyword search. The user provides a term and the <code>sourceDialect<\/code> platform they already know it in (<code>postgresql<\/code>, <code>mysql<\/code>, <code>sqlserver<\/code>, or <code>oracle<\/code>), then chooses <code>targetDialects<\/code> \u2014 one, several, or all of the remaining platforms \u2014 and gets back the equivalent term(s) on those platforms.<\/em><\/p>\n\n\n\n<p><em><strong>Migration<\/strong> \u2014 Add <code>migrations\/V4__add_term_equivalents_dialect_fk.sql<\/code>:<\/em><\/p>\n\n\n\n<p><em>Add nullable <code>dialect_id<\/code> INTEGER to <code>dbrosetta.term_equivalents<\/code>, with FOREIGN KEY (<code>dialect_id<\/code>) REFERENCES <code>dbrosetta.dialects(id)<\/code>.<\/em><\/p>\n\n\n\n<p><em>Backfill <code>dialect_id<\/code> by matching existing platform values to <code>dialects.name<\/code> or <code>dialects.display_name<\/code> case-insensitively (e.g. &#8216;SQL Server&#8217; \u2192 the <code>sqlserver<\/code> dialect). Rows with no match (the SQLite rows) keep <code>dialect_id<\/code> NULL.<\/em><\/p>\n\n\n\n<p><em>Add <code>index idx_term_equivalents_dialect<\/code> on <code>dialect_id<\/code>.<\/em><\/p>\n\n\n\n<p><em>Add a partial unique constraint on (<code>term_id<\/code>, <code>dialect_id<\/code>) where <code>dialect_id<\/code> IS NOT NULL.<\/em><\/p>\n\n\n\n<p><em>Do not drop the platform column or the existing <code>uq_term_equivalents_term_platform<\/code> constraint.<\/em><\/p>\n\n\n\n<p><em><strong>Prisma schema<\/strong> (services\/dbrosetta-api\/prisma\/schema.prisma) \u2014 mirror the migration exactly: add optional <code>dialectId Int?<\/code> and a <code>dialect Dialect?<\/code> relation on <code>TermEquivalent<\/code>, add the reverse relation on <code>Dialect<\/code>, add the index. Regenerate the client as part of your work.<\/em><\/p>\n\n\n\n<p><em><strong>New API route<\/strong> \u2014 Add POST \/api\/v1\/terms\/lookup (new file services\/dbrosetta-api\/src\/routes\/v1\/term-lookup.ts, registered in routes\/v1\/index.ts). Validate sourceDialect\/targetDialects with zod against active dialects (400 with error: &#8220;invalid_dialect&#8221; on failure). Implement the two-step matching rule from the Guardrails section, and shape the response exactly per the Output Contract. Return 404 with error: &#8220;not_found&#8221; when nothing matches. Add unit tests in src\/__tests__ covering: successful single-target lookup, successful &#8220;all platforms&#8221; lookup (source excluded), the canonical-term fallback path, invalid dialect (400), and unknown term (404).<\/em><\/p>\n\n\n\n<p><em><strong>Seed data<\/strong> \u2014 Update services\/dbrosetta-api\/prisma\/seed.ts to add the 8 new terms and their per-platform equivalents listed in &#8220;Seed Data&#8221; below, using the same upsert\/createMany pattern already used for the WAL term. Keep it idempotent (safe to re-run).<\/em><\/p>\n\n\n\n<p><em><strong>WordPress plugin<\/strong>:<br>includes\/class-dbrosetta-client.php: add lookup_term_equivalents(string $term, string $sourceDialect, array $targetDialects = []) that POSTs { term, sourceDialect, targetDialects } to \/terms\/lookup and returns the decoded response or a WP_Error. Keep the existing get_dialects() method \u2014 use it to drive both dropdowns\/checkboxes instead of any hardcoded option list.<\/em><\/p>\n\n\n\n<p><em>templates\/search-form.php: replace the current form with: a term text input (required); a required single-select &#8220;I know this term in&#8221; dropdown built from get_dialects(); a &#8220;Translate to&#8221; control offering an &#8220;All platforms&#8221; checkbox plus one checkbox per dialect (also built from get_dialects()), letting the user pick one, several, or all.<\/em><\/p>\n\n\n\n<p><em>dbrosetta.php: update the shortcode handler to read term, source_dialect, and target_dialects[] from $_POST, sanitize each, require term and source_dialect, and call the new client method instead of search_terms().<\/em><\/p>\n\n\n\n<p><em>templates\/search-results.php: replace the current results block with rendering for the new response shape \u2014 the term&#8217;s description, the confirmed source-platform equivalent, and a Platform | Equivalent Term | Notes table for the returned results. Reuse the existing .dbrosetta-equivalents \/ .dbrosetta-table CSS classes where they fit; add only the minimal new CSS needed for the &#8220;All platforms&#8221; + checkbox control in assets\/dbrosetta.css. On 404, reuse the existing &#8220;no results&#8221; block style with a message naming the term and source platform.<\/em><\/p>\n\n\n\n<p><em><strong>Seed Data (use verbatim \u2014 do not alter or invent facts)<\/strong><br>For each concept below, create one Term (canonicalTerm\/category\/subcategory\/description as given) and one TermEquivalent row per platform (platform string + notes as given; dialectId resolved from the matching dialect).<\/em><\/p>\n\n\n\n<p><em><strong>Buffer Pool \/ Buffer Cache<\/strong> \u2014 category System, subcategory Memory \u2014 description: &#8220;The in-memory cache of recently used data pages that reduces physical disk I\/O.&#8221;<br>SQL Server: Buffer Pool \u2014 &#8220;Managed as part of sys.dm_os_buffer_descriptors; sized via &#8216;max server memory&#8217;.&#8221;<\/em><\/p>\n\n\n\n<p><em>PostgreSQL: Shared Buffers \u2014 &#8220;Configured via the shared_buffers setting; PostgreSQL also relies heavily on the OS page cache.&#8221;<\/em><\/p>\n\n\n\n<p><em>Oracle: Database Buffer Cache \u2014 &#8220;Part of the SGA; sized via DB_CACHE_SIZE or automatic memory management.&#8221;<\/em><\/p>\n\n\n\n<p><em>MySQL: InnoDB Buffer Pool \u2014 &#8220;Configured via innodb_buffer_pool_size; caches both data and indexes for InnoDB tables.&#8221;<\/em><\/p>\n\n\n\n<p><em><strong>Row Versioning \/ MVCC Mechanism<\/strong> \u2014 category System, subcategory Concurrency \u2014 description: &#8220;The mechanism that lets readers see a consistent snapshot of data without blocking writers, by keeping prior versions of changed rows.&#8221;<\/em><\/p>\n\n\n\n<p><em>SQL Server: Version Store \u2014 &#8220;Lives in tempdb; used by snapshot isolation and read-committed snapshot isolation (RCSI).&#8221;<\/em><\/p>\n\n\n\n<p><em>PostgreSQL: MVCC \u2014 &#8220;Multiversion Concurrency Control; old row versions are retained until vacuumed, and changes are protected by the WAL.&#8221;<\/em><\/p>\n\n\n\n<p><em>Oracle: Undo Segments \u2014 &#8220;Undo tablespace stores before-images used for read consistency and rollback.&#8221;<br>MySQL: InnoDB Undo Logs \u2014 &#8220;InnoDB&#8217;s MVCC implementation; undo logs support both rollback and consistent non-locking reads.&#8221;<\/em><\/p>\n\n\n\n<p><em><strong>Clustered Table Storage<\/strong> \u2014 category System, subcategory Storage \u2014 description: &#8220;Whether and how a table&#8217;s data rows are physically ordered on disk according to a key.&#8221;<\/em><\/p>\n\n\n\n<p><em>SQL Server: Clustered Index \u2014 &#8220;A table has at most one; data rows are stored in key order in the index&#8217;s leaf level.&#8221;<\/em><\/p>\n\n\n\n<p><em>PostgreSQL: Heap Table (no persistent clustering) \u2014 &#8220;Tables are unordered heaps by default; CLUSTER reorders rows once but does not maintain order on later writes.&#8221;<\/em><\/p>\n\n\n\n<p><em>Oracle: Index-Organized Table (IOT) \u2014 &#8220;An alternative to a normal heap table where the table itself is stored as a B-tree index on its primary key.&#8221;<\/em><\/p>\n\n\n\n<p><em>MySQL: Clustered Index (InnoDB Primary Key) \u2014 &#8220;InnoDB always clusters the table by its primary key; a table without an explicit primary key gets a hidden one.&#8221;<\/em><\/p>\n\n\n\n<p><em><strong>Identity \/ Auto-Increment Column<\/strong> \u2014 category DDL, subcategory Schema \u2014 description: &#8220;A column that automatically generates a unique, incrementing value for new rows.&#8221;<\/em><\/p>\n\n\n\n<p><em>SQL Server: IDENTITY \u2014 &#8220;IDENTITY(seed, increment) property on a column.&#8221;<\/em><\/p>\n\n\n\n<p><em>PostgreSQL: GENERATED ALWAYS AS IDENTITY \/ SERIAL \u2014 &#8220;SQL-standard IDENTITY columns (preferred) or the legacy SERIAL pseudo-type backed by a sequence.&#8221;<\/em><\/p>\n\n\n\n<p><em>Oracle: IDENTITY Column \u2014 &#8220;Native IDENTITY columns since 12c; earlier versions combine a SEQUENCE with a trigger.&#8221;<\/em><\/p>\n\n\n\n<p><em>MySQL: AUTO_INCREMENT \u2014 &#8220;AUTO_INCREMENT column attribute; only one per table, and it must be indexed.&#8221;<\/em><\/p>\n\n\n\n<p><em><strong>Temporary Workspace for Sorts\/Spills<\/strong> \u2014 category System, subcategory Storage \u2014 description: &#8220;The storage area the database engine uses for sort operations, hash joins, and other data that spills to disk.&#8221;<\/em><\/p>\n\n\n\n<p><em>SQL Server: tempdb \u2014 &#8220;A shared system database used for temp tables, sort\/hash spills, and the version store.&#8221;<\/em><\/p>\n\n\n\n<p><em>PostgreSQL: temp_tablespaces \/ Temporary Files \u2014 &#8220;Configured via temp_tablespaces; spill files are written under the pgsql_tmp directory.&#8221;<\/em><\/p>\n\n\n\n<p><em>Oracle: TEMP Tablespace \u2014 &#8220;A dedicated temporary tablespace used for sorts, hash joins, and global temporary tables.&#8221;<\/em><\/p>\n\n\n\n<p><em>MySQL: tmpdir \/ Internal Temporary Tables \u2014 &#8220;Controlled by the tmpdir setting; internal temp tables may be in-memory or on-disk depending on size and engine.&#8221;<\/em><\/p>\n\n\n\n<p><em><strong>Deadlock Diagnostic Artifact<\/strong> \u2014 category System, subcategory Concurrency \u2014 description: &#8220;The information the engine records when it detects and breaks a deadlock, used to diagnose the conflicting transactions.&#8221;<\/em><\/p>\n\n\n\n<p><em>SQL Server: Deadlock Graph \u2014 &#8220;An XML deadlock graph captured via Extended Events (or the older trace flag 1222).&#8221;<\/em><\/p>\n\n\n\n<p><em>PostgreSQL: Deadlock Detected Log Entry \u2014 &#8220;Logged to the server log when log_lock_waits\/deadlock_timeout trigger detection; no XML graph, just structured log text.&#8221;<\/em><\/p>\n\n\n\n<p><em>Oracle: ORA-00060 Deadlock Trace File \u2014 &#8220;Oracle raises ORA-00060 and writes a trace file to the diagnostic destination describing the waiters.&#8221;<\/em><\/p>\n\n\n\n<p><em>MySQL: LATEST DETECTED DEADLOCK \u2014 &#8220;Found in the output of SHOW ENGINE INNODB STATUS, describing the transactions and locks involved.&#8221;<\/em><\/p>\n\n\n\n<p><em><strong>Query Execution Plan<\/strong> \u2014 category DQL, subcategory Query \u2014 description: &#8220;The plan the optimizer chooses to physically execute a query, showing operators, order, and estimated\/actual cost.&#8221;<\/em><\/p>\n\n\n\n<p><em>SQL Server: Execution Plan \u2014 &#8220;Viewable as estimated or actual plans, graphically or as XML, via SSMS or SET SHOWPLAN options.&#8221;<\/em><\/p>\n\n\n\n<p><em>PostgreSQL: Query Plan (EXPLAIN) \u2014 &#8220;Produced by EXPLAIN [ANALYZE]; text-based tree of plan nodes with costs and, with ANALYZE, actual timings.&#8221;<\/em><\/p>\n\n\n\n<p><em>Oracle: Explain Plan \u2014 &#8220;Produced by EXPLAIN PLAN FOR or the SQL*Plus AUTOTRACE\/DBMS_XPLAN utilities.&#8221;<\/em><\/p>\n\n\n\n<p><em>MySQL: EXPLAIN Output \u2014 &#8220;Produced by EXPLAIN [ANALYZE] or the optimizer trace; tabular by default, tree-style with EXPLAIN FORMAT=TREE.&#8221;<\/em><\/p>\n\n\n\n<p><em><strong>Optimizer Statistics<\/strong> \u2014 category System, subcategory Query Optimization \u2014 description: &#8220;The metadata about data distribution and cardinality that the query optimizer uses to choose a plan.&#8221;<\/em><\/p>\n\n\n\n<p><em>SQL Server: Statistics \u2014 &#8220;Objects visible in sys.stats; maintained automatically via AUTO_CREATE_STATISTICS\/AUTO_UPDATE_STATISTICS.&#8221;<\/em><\/p>\n\n\n\n<p><em>PostgreSQL: Planner Statistics \u2014 &#8220;Collected by ANALYZE (often via autovacuum) and stored in pg_statistic; consumed by the planner via pg_stats.&#8221;<\/em><\/p>\n\n\n\n<p><em>Oracle: Optimizer Statistics \u2014 &#8220;Gathered and managed via the DBMS_STATS package, typically on an automated maintenance job.&#8221;<\/em><\/p>\n\n\n\n<p><em>MySQL: Index\/Table Statistics \u2014 &#8220;InnoDB persistent optimizer statistics (innodb_stats_persistent) refreshed by ANALYZE TABLE or background sampling.&#8221;<\/em><\/p>\n\n\n\n<p><em><strong>Examples (minimum required)<\/strong><\/em><\/p>\n\n\n\n<p><em>prompts\/examples\/directional-term-lookup\/fixtures\/minimal\/input.json -&gt; prompts\/examples\/directional-term-lookup\/expected\/minimal\/output.json (happy path: single target platform)<\/em><\/p>\n\n\n\n<p><em>prompts\/examples\/directional-term-lookup\/fixtures\/edge\/input.json -&gt; prompts\/examples\/directional-term-lookup\/expected\/edge\/output.json (all-platforms, source excluded, case-insensitive input)<\/em><\/p>\n\n\n\n<p><em>prompts\/examples\/directional-term-lookup\/fixtures\/no-match\/input.json -&gt; prompts\/examples\/directional-term-lookup\/expected\/no-match\/output.json (unknown term, 404)<\/em><\/p>\n\n\n\n<p><em><strong>Post Processing<\/strong><\/em><\/p>\n\n\n\n<p><em>Run npx prisma generate and npx prisma migrate diff (or equivalent) to confirm the Prisma schema matches migration V4 before committing.<\/em><\/p>\n\n\n\n<p><em>Run flyway validate and flyway migrate against a local\/dev database to confirm V4 applies cleanly on top of V1\u2013V3.<\/em><\/p>\n\n\n\n<p><em>Run npm test in services\/dbrosetta-api (unit tests, including the new term-lookup tests) and npm run seed to confirm the seed script is idempotent (run it twice, diff row counts).<\/em><\/p>\n\n\n\n<p><em>Manually smoke-test the three fixtures below against the running API with curl\/Postman and diff the response against the expected output (ignoring timestamps\/ids).<\/em><\/p>\n\n\n\n<p><em>Load the WordPress shortcode locally (or in a staging environment) and visually confirm: the source dropdown and target checkboxes are populated from \/dialects, &#8220;All platforms&#8221; excludes the source platform from results, and the 404 case renders the existing no-results styling.<\/em><\/p>\n\n\n\n<p><em>Artifact persistence: write run artifacts (test output, migration output, screenshots if applicable) to artifacts\/&lt;run_id&gt;\/.<\/em><\/p>\n\n\n\n<p><em><strong>Telemetry keys to record<\/strong><br>prompt_version, model_settings, fixtures_hash, run_id, timestamp<\/em><\/p>\n\n\n\n<p><em><strong>Notes<\/strong><br>This supersedes the search behavior originally specified in prompts\/iterate-the-design-first-pass.md. The SQL-syntax translation feature (the translations table, Translation Prisma model, and its grid in the old search-results.php) is intentionally left in place structurally but removed from this page&#8217;s UI \u2014 it may get its own shortcode\/page in a future pass, but that is out of scope here. SQLite remains only as legacy free-text data in term_equivalents and should not be added to dialects or exposed in the UI as part of this change.<\/em><\/p>\n\n\n\n<p><em>Location for fixtures: prompts\/examples\/directional-term-lookup\/<\/em><\/p>\n\n<\/div>\n<\/div> \n\n\n<p>I\u2019m not joking when I say I\u2019m <em>excited<\/em> to see what Claude Code makes of this crazy prompt!<\/p>\n\n\n\n<p>A key point I should make here: when I started this project, I wasn\u2019t as experienced with the use of <a href=\"https:\/\/www.ibm.com\/think\/topics\/agentic-ai\" target=\"_blank\" rel=\"noreferrer noopener\">Agentic AI<\/a> as I am now. I&#8217;ve learned a lot in this time. <\/p>\n\n\n\n<p>For example, I&#8217;d now <em>absolutely<\/em> insist on a few more things from the AI at this point. I would push it to keep a log of what worked and what didn\u2019t to avoid doing something silly multiple times. I would also be clearer about defining any measures needed to ensure the work is successful.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-you-did-what-claude-when-the-ai-acts-without-asking\">You did <em>what<\/em>, Claude?! (When the AI acts <em>without asking<\/em>)<\/h2>\n\n\n\n<p>I\u2019m sitting there watching Claude Code do it\u2019s thing &#8211; <em>Determining<\/em>, <em>Honking<\/em>, <em>Noodling<\/em> &#8211; when I notice it&#8217;s gone on a search through my laptop to see if there\u2019s a running instance of PostgreSQL. There wasn\u2019t, but it found my shutdown PostgreSQL installation and fired it up. <\/p>\n\n\n\n<p>And I\u2019m about to have a cow when I realize why: it wanted to validate the database changes and code <em>before<\/em> it tried to deploy.<\/p>\n\n\n\n<p>You could have knocked me over with a feather.<\/p>\n\n\n\n<p>I mean, look. Spelunking through my system trying to find a <a href=\"https:\/\/www.red-gate.com\/simple-talk\/other\/creating-an-azure-postgresql-cluster-and-connecting-to-it\/\" target=\"_blank\" rel=\"noreferrer noopener\">PostgreSQL cluster<\/a> to connect to &#8211; yeah, I&#8217;m not happy with that. But making darned sure it can <em>validate<\/em> stuff before deploying it? HALLELUJAH!<\/p>\n\n\n\n<p>Where we arrived, I had a functional app with all the changes I outlined. <em>Cool.<\/em> I went to test it, entered the one example I gave, and simply assumed it would be there. The response was as expected: <em>\u2018transaction log\u2019<\/em>, and there was no data returned. <\/p>\n\n\n\n<p>OK. This is fine.<\/p>\n\n\n\n<p>I go back and ask <a href=\"https:\/\/code.visualstudio.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Visual Studio (VS) Code<\/a> and it does a little digging, determining that the <a href=\"https:\/\/www.prisma.io\/docs\/orm\/v7\/prisma-migrate\/workflows\/seeding\" target=\"_blank\" rel=\"noreferrer noopener\">Prisma seed<\/a> script for updating the database hadn\u2019t run. The <em>what<\/em> now?<\/p>\n\n\n\n<p>Yeah, it had used <a href=\"https:\/\/v1.prisma.io\/docs\/1.34\/understand-prisma\/prisma-introduction-what-why-how-j9ff\/\" target=\"_blank\" rel=\"noreferrer noopener\">Prisma<\/a> as an <a href=\"https:\/\/www.red-gate.com\/simple-talk\/development\/dotnet-development\/under-the-orm-hood-revealing-the-sql\/#:~:text=an%20ORM%20refers%20to%20any%20software%20program%20intended%20to%20map%20data%20between%20two%20incompatible%20systems%2C%20the%20domain%2Dbased%20object%20model%20of%20the%20data%2C%20and%20the%20relational%20database%20model.\" target=\"_blank\" rel=\"noreferrer noopener\">ORM (object-relational mapping)<\/a>, and then decided to start doing database deployments through it &#8211; despite <em>all<\/em> our other deployments going through <a href=\"https:\/\/www.red-gate.com\/products\/flyway\/\" target=\"_blank\" rel=\"noreferrer noopener\">Redgate Flyway<\/a>. So, we had to roll that work back out of the code and then move it all into a <a href=\"https:\/\/www.red-gate.com\/simple-talk\/databases\/sql-server\/database-administration-sql-server\/using-migration-scripts-in-database-deployments\/\" target=\"_blank\" rel=\"noreferrer noopener\">migration script<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-what-i-learned-again\">What I learned (again)<\/h2>\n\n\n\n<p><strong>I feel like I\u2019ve worked hard on getting guidance and guardrails in place over <em>how<\/em> the AI behaves. Yet still, the darned thing just seemingly bypasses them all when it\u2019s in a mood. It\u2019s reinforcing to me, repeatedly, that you absolutely must build a great big barrier between this insanely useful tool and your production systems. <\/strong><\/p>\n\n\n\n<p><strong>AI is truly useful &#8211; but also wildly dangerous. Nothing I\u2019ve done with it has <em>hurt<\/em>, but it&#8217;s only ever deploying through a defined pipeline. It\u2019s not able to directly access <em>\u201cproduction\u201d<\/em> in a meaningful way.<\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-the-3-key-takeaways-from-my-experience\">The 3 key takeaways from my experience<\/h2>\n\n\n\n<p>Here are the <strong>3 key takeaways<\/strong> from my trials and tribulations. It&#8217;s what I learned, to help <em>you<\/em> not repeat the same mistakes!<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-don-t-come-into-an-old-project-with-new-assumptions\">Don\u2019t come into an old project with new assumptions<\/h3>\n\n\n\n<p>I\u2019ve picked up quite a few new methods since I started this project. Silly me, I assumed they were in place. <strong>I should have told the AI to keep a log of what it attempted, what worked and what didn\u2019t<\/strong> &#8211; stuff like that.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-different-engines-are-different\">Different engines are&#8230;different<\/h3>\n\n\n\n<p>Comparing Claude and CoPilot&#8217;s answers to my various prompts for this project, you really see differences in behavior. Granted, the same prompt submitted twice in the same engine can also result in differences answers. <\/p>\n\n\n\n<p><strong>However, <em>answers<\/em> and <em>behavior<\/em> are two completely different things. It&#8217;s only when you change the AI engine that you notice the differences in behavior.<\/strong><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-re-examine-everything-if-when-you-change-ai-engine\">Re-examine <em>everything<\/em> if\/when you change AI engine<\/h3>\n\n\n\n<p>I went at this like <em>&#8216;meh, they\u2019ll basically be the same in their behavior.&#8217;<\/em>&#8216; Well, as made clear above, they are <em>not<\/em> the same! Sure, some patterns are the same (why do they want to deploy with that ORM tool so badly?), but others are unique. <\/p>\n\n\n\n<p><strong>Even with a valid and tested set of guidelines, if you swap the AI engine you&#8217;re using, you probably need to re-examine<\/strong> <strong>them &#8211; and how you work with the tool in general.<\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-the-last-word-claude-s-take-on-dbrosetta-right-now\">The last word: Claude\u2019s take on dbRosetta <em>right now<\/em><\/h2>\n\n\n\n<p>I asked Claude where it thinks dbRosetta stands <em>right now<\/em>. Here&#8217;s its response:<\/p>\n\n\n\n<div id=\"callout-block_034a4748061f10d717be7c2d147626c7\" class=\"callout alignnone\">\n    <div class=\"child-last:mb-0 child-first:mt-0 bg-gray-50 dark:bg-gray-950 p-4xl my-3xl\">\n\n<p><em>The core feature work is sound: the schema change was additive, the API contract was specific enough to leave little room for invention, and the plugin now answers the question you actually want answered instead of a generic keyword search. The deployment story is more turnkey too. None of that makes dbRosetta production software, but the discipline underneath it \u2014 Flyway-only schema changes, admin-gated writes, HTTPS-only calls \u2014 is real, and it&#8217;s what caught the Prisma detour before it did damage.<\/em><\/p>\n\n\n\n<p><em>That detour is the more honest data point. Given a database change, I reached for the ORM&#8217;s own deploy path instead of the migration tool the project actually requires, and went looking for a Postgres instance on your machine without asking \u2014 a good instinct (validate before shipping) executed as an unauthorized action. Both were caught by you noticing a symptom, not by anything stopping the behavior at the source. Worth remembering as you widen my Azure access: scope that credential tighter than feels necessary, and verify compliance in the diff, not the prompt.<\/em><\/p>\n\n<\/div>\n<\/div> \n\n\n<section id=\"my-first-block-block_7071dbeaeda7cd12891ec6f2dcc726f1\" class=\"my-first-block alignwide\">\n    <div class=\"bg-brand-600 text-base-white py-5xl px-4xl rounded-sm bg-gradient-to-r from-brand-600 to-brand-500 red\">\n        <div class=\"gap-4xl items-start md:items-center flex flex-col md:flex-row justify-between\">\n            <div class=\"flex-1 col-span-10 lg:col-span-7\">\n                <h3 class=\"mt-0 font-display mb-2 text-display-sm\">Simple Talk is brought to you by Redgate Software<\/h3>\n                <div class=\"child:last-of-type:mb-0\">\n                                            Take control of your databases with the trusted Database DevOps solutions provider. Automate with confidence, scale securely, and unlock growth through AI.                                    <\/div>\n            <\/div>\n                                            <a href=\"https:\/\/www.red-gate.com\/solutions\/overview\/\" class=\"btn btn--secondary btn--lg\" aria-label=\"Discover how Redgate can help you: Simple Talk is brought to you by Redgate Software\">Discover how Redgate can help you<\/a>\n                    <\/div>\n    <\/div>\n<\/section>\n\n\n<section id=\"faq\" class=\"faq-block my-5xl\">\n    <h2>FAQs<\/h2>\n\n                        <h3 class=\"mt-4xl\">1. What feature was added to dbRosetta in this part of the series?<\/h3>\n            <div class=\"faq-answer\">\n                <p>A directional term-lookup feature that replaces the original keyword search: users pick the platform they already know a term in, then choose one or more target platforms to see the equivalent term on each.<\/p>\n            <\/div>\n                    <h3 class=\"mt-4xl\">2. What did the AI agent do without being asked?<\/h3>\n            <div class=\"faq-answer\">\n                <p>It searched the author&#8217;s laptop for a running PostgreSQL instance to validate database changes before deploying, found a shut-down installation, and started it up on its own.<\/p>\n            <\/div>\n                    <h3 class=\"mt-4xl\">3. Did the AI cause any deployment problems?<\/h3>\n            <div class=\"faq-answer\">\n                <p>Yes. It used Prisma&#8217;s own deployment path for a database change instead of Flyway, the migration tool the project actually requires, so the author had to roll that work back out and move it into a proper migration script.<\/p>\n            <\/div>\n                    <h3 class=\"mt-4xl\">4. What&#039;s the main lesson from this part of the series?<\/h3>\n            <div class=\"faq-answer\">\n                <p>That guardrails and guidelines you&#8217;ve set for an AI agent can <em>still<\/em> get bypassed, so anything touching real infrastructure needs a defined pipeline between the AI and production &#8211; not just trust in the prompt.<\/p>\n            <\/div>\n            <\/section>\n","protected":false},"excerpt":{"rendered":"<p>How to build an app through an LLM: switching from CoPilot to Claude, a directional term-lookup feature, and an AI agent that made an unauthorized move.&hellip;<\/p>\n","protected":false},"author":221792,"featured_media":103500,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[159169,143523,53,143533,143534,143524],"tags":[159075,4168,4170,159395,4459,158978,4150,4151],"coauthors":[6785],"class_list":["post-112594","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ai","category-databases","category-featured","category-oracle-databases","category-postgresql","category-sql-server","tag-ai","tag-database","tag-database-administration","tag-how-i-built-an-app-ai-llm","tag-oracle","tag-postgresql","tag-sql","tag-sql-server"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/112594","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/221792"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=112594"}],"version-history":[{"count":19,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/112594\/revisions"}],"predecessor-version":[{"id":112889,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/112594\/revisions\/112889"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media\/103500"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=112594"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=112594"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=112594"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=112594"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}