<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: sep83</title>
    <description>The latest articles on DEV Community by sep83 (@sep83).</description>
    <link>https://dev.to/sep83</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3760391%2Fc403635d-8b35-4f28-b7f5-c25baef594b8.png</url>
      <title>DEV Community: sep83</title>
      <link>https://dev.to/sep83</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sep83"/>
    <language>en</language>
    <item>
      <title>No More Hallucinated Citations: A Domain-Specific RAG System with Ollama, ChromaDB and AI Agents</title>
      <dc:creator>sep83</dc:creator>
      <pubDate>Mon, 11 May 2026 02:27:38 +0000</pubDate>
      <link>https://dev.to/sep83/no-more-hallucinated-citations-a-domain-specific-rag-system-with-ollama-chromadb-and-ai-agents-30c5</link>
      <guid>https://dev.to/sep83/no-more-hallucinated-citations-a-domain-specific-rag-system-with-ollama-chromadb-and-ai-agents-30c5</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; I built a full-stack knowledge pipeline around a corpus of 2,514 academic PDFs focused on urban art. The system combines ChromaDB vector search, Ollama-powered semantic analysis, a FastAPI REST layer, and six AI agents (slash commands in Claude Code) that orchestrate research workflows end-to-end. The result: zero hallucinated citations, dense evidence-backed documents, and a workflow that scales to any specialized domain.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The Problem: LLMs Hallucinate Academic Citations
&lt;/h2&gt;

&lt;p&gt;If you've ever used an LLM to help write a research proposal or academic paper, you've probably hit this wall: the model confidently produces author names, journal titles, and publication years — none of which exist.&lt;/p&gt;

&lt;p&gt;The standard advice is "don't use AI for citations." But that advice ignores a better question: &lt;em&gt;what if you gave the model an authoritative, queryable corpus instead of relying on its training data?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That's exactly what this system does.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Stack at a Glance
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PDFs (2,514 docs, 4 languages)
        │
        ▼
  [Ingestion Pipeline]
   pdfplumber → chunking → metadata extraction
        │
        ▼
  [Dual Storage]
   MariaDB (corpus.db) ──── ChromaDB (59,030 chunks)
   metadata + citations      vector embeddings
        │
        ▼
  [Analysis Layer]
   Ollama (self-hosted LLM) — semantic relevance scoring,
   research_hint generation, debate mapping
        │
        ▼
  [REST API — FastAPI]
   /search · /consulta · /fragmentos · /autores
   /debate · /translate · /recientes · /document/{id}
        │
        ▼
  [AI Agent Layer — Claude Code slash commands]
   /mapeador · /evidencia · /auditor · /propuesta · /articulo · /vigilante
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything runs locally. No data leaves the machine. The corpus, embeddings, LLM inference, and API are all self-hosted.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 1 — The Corpus
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Ingestion
&lt;/h3&gt;

&lt;p&gt;The corpus started with a focused collection of academic PDFs on urban art and graffiti: peer-reviewed articles, book chapters, conference proceedings, and policy documents spanning English, Spanish, Portuguese, and French.&lt;/p&gt;

&lt;p&gt;Each document goes through a pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Simplified ingestion flow
&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;extract_text_pdfplumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pdf_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;chunks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;split_into_paragraphs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;overlap&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;extract_metadata&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# author, year, DOI, language
&lt;/span&gt;    &lt;span class="n"&gt;embedding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;embed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;       &lt;span class="c1"&gt;# via Ollama nomic-embed-text
&lt;/span&gt;    &lt;span class="n"&gt;chromadb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;embedding&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;mariadb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="c1"&gt;# full text + APA citation
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The chunking strategy matters enormously here. Fixed-size token splitting loses paragraph context. Instead, I split on paragraph boundaries with a 64-token overlap between chunks, which preserves semantic coherence while keeping retrieval granular.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Gets Stored
&lt;/h3&gt;

&lt;p&gt;Each chunk in MariaDB carries:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;paragraph&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Full text of the chunk&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;page&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Page number in the original PDF&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;citation_apa&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Pre-formatted APA 7 citation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;citation_mla&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Pre-formatted MLA citation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;doc_id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Unique document identifier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;relevancia&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Ollama-assigned relevance score (1–5)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;research_hint&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;≤240-char synthesis of the chunk's contribution&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;categoria_tematica&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Thematic category (e.g., &lt;code&gt;graffiti_core&lt;/code&gt;, &lt;code&gt;tecnologia&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;anio&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Publication year&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;idioma&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Language code&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;relevancia&lt;/code&gt; field is generated once at ingestion time by asking Ollama to score each chunk's relevance to the corpus domain. This pre-computation means searches can filter by quality without running LLM inference at query time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Current State
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Total documents:    2,514
Chunks in ChromaDB: 59,030
RAG coverage:       99.8%
Languages:          EN (62.3%), ES (14.3%), PT (12.7%), FR (2.7%), others
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Part 2 — The Retrieval Layer
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Hybrid Search
&lt;/h3&gt;

&lt;p&gt;A common mistake in RAG systems is relying solely on cosine similarity. Semantic similarity isn't the same as relevance — a chunk can be &lt;em&gt;about&lt;/em&gt; the right topic but still be a weak citation (methodologically unsound, pre-2010, tangential argument).&lt;/p&gt;

&lt;p&gt;The system uses a hybrid &lt;code&gt;relevance_score&lt;/code&gt; that combines three signals:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;relevance_score&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="mf"&gt;0.5&lt;/span&gt; &lt;span class="err"&gt;×&lt;/span&gt; &lt;span class="nf"&gt;cosine_similarity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query_embedding&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chunk_embedding&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;0.3&lt;/span&gt; &lt;span class="err"&gt;×&lt;/span&gt; &lt;span class="n"&gt;ollama_relevancia&lt;/span&gt;          &lt;span class="c1"&gt;# pre-computed quality score
&lt;/span&gt;  &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt; &lt;span class="err"&gt;×&lt;/span&gt; &lt;span class="nf"&gt;recency_weight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;       &lt;span class="c1"&gt;# normalized publication year
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This produces meaningfully different rankings from pure vector search — and in practice surfaces much better citations for academic use.&lt;/p&gt;

&lt;h3&gt;
  
  
  The API Endpoints
&lt;/h3&gt;

&lt;p&gt;The FastAPI layer exposes the corpus as a set of purpose-built endpoints:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Semantic search — fast, no LLM at query time&lt;/span&gt;
GET /search?q&lt;span class="o"&gt;=&lt;/span&gt;urban+heritage+documentation&amp;amp;top_k&lt;span class="o"&gt;=&lt;/span&gt;20&amp;amp;style&lt;span class="o"&gt;=&lt;/span&gt;apa

&lt;span class="c"&gt;# Full RAG — slower, synthesizes an answer with citations&lt;/span&gt;
POST /consulta
&lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"pregunta"&lt;/span&gt;: &lt;span class="s2"&gt;"What methods exist for documenting ephemeral urban art?"&lt;/span&gt;,
  &lt;span class="s2"&gt;"top_k"&lt;/span&gt;: 10,
  &lt;span class="s2"&gt;"anio_desde"&lt;/span&gt;: 2015,
  &lt;span class="s2"&gt;"idioma"&lt;/span&gt;: &lt;span class="s2"&gt;"en"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# Verbatim fragments for direct quotation&lt;/span&gt;
GET /fragmentos?concepto&lt;span class="o"&gt;=&lt;/span&gt;ephemeral+art+preservation&amp;amp;top_k&lt;span class="o"&gt;=&lt;/span&gt;8

&lt;span class="c"&gt;# Author and debate mapping&lt;/span&gt;
GET /autores?tema&lt;span class="o"&gt;=&lt;/span&gt;digital+documentation+street+art
GET /debate?tema&lt;span class="o"&gt;=&lt;/span&gt;vandalism+vs+heritage

&lt;span class="c"&gt;# Export for bibliography sections&lt;/span&gt;
GET /search/export?q&lt;span class="o"&gt;=&lt;/span&gt;graffiti+cultural+heritage&amp;amp;format&lt;span class="o"&gt;=&lt;/span&gt;bib&amp;amp;top_k&lt;span class="o"&gt;=&lt;/span&gt;100

&lt;span class="c"&gt;# Translation of non-native-language chunks&lt;/span&gt;
POST /translate
&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"paragraph"&lt;/span&gt;: &lt;span class="s2"&gt;"..."&lt;/span&gt;, &lt;span class="s2"&gt;"target_lang"&lt;/span&gt;: &lt;span class="s2"&gt;"es"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each endpoint returns structured data including &lt;code&gt;paragraph&lt;/code&gt;, &lt;code&gt;page&lt;/code&gt;, &lt;code&gt;citation_apa&lt;/code&gt;, &lt;code&gt;relevance_score&lt;/code&gt;, &lt;code&gt;research_hint&lt;/code&gt;, and &lt;code&gt;doc_id&lt;/code&gt;. The &lt;code&gt;doc_id&lt;/code&gt; is critical — it makes every citation traceable back to a specific PDF page.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example Response from &lt;code&gt;/fragmentos&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"results"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"paragraph"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Street art occupies a paradoxical position in urban space: simultaneously celebrated as cultural expression and prosecuted as criminal damage, its ephemerality is not accidental but constitutive of its meaning..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"page"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;47&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"citation_apa"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Brighenti, A. M. (2010). At the wall: Graffiti writers, urban territoriality, and the public domain. Space and Culture, 13(3), 315–332. https://doi.org/10.1177/1206331210365283"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"relevance_score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.91&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"research_hint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Argues ephemerality is constitutive of street art's meaning, not a deficiency — critical for patrimony arguments."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"doc_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"brighenti_2010_wall"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the &lt;code&gt;research_hint&lt;/code&gt; — this is Ollama's pre-computed synthesis of &lt;em&gt;why&lt;/em&gt; the chunk matters, not just what it says. It's what makes the agent layer possible.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 3 — The Agent Layer
&lt;/h2&gt;

&lt;p&gt;The real productivity multiplier isn't the API — it's the agents built on top of it.&lt;/p&gt;

&lt;p&gt;Six Claude Code slash commands orchestrate the research workflow. Each agent is a Markdown file in &lt;code&gt;.claude/commands/&lt;/code&gt; that instructs Claude Code to call the corpus API in a specific sequence and produce structured output files.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Agent Map
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/vigilante   — session start: check deadlines, detect new corpus documents
/mapeador    — map the corpus for a topic (calls /autores + /debate + /search ×2 + /consulta ×2)
/evidencia   — build an evidence table for a specific section
/propuesta   — full proposal generator (orchestrates mapeador + evidencia + redaction)
/articulo    — full IMRAD academic article generator
/auditor     — audit any .md file, classifying claims as [✓ VERIFIED] / [⚠ WEAK] / [✗ PENDING]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The &lt;code&gt;/mapeador&lt;/code&gt; Agent — Eliminating 6 Manual API Calls
&lt;/h3&gt;

&lt;p&gt;The most impactful agent. Before it existed, mapping the corpus for a new topic meant manually calling six endpoints, collecting outputs, and synthesizing them into a coherent picture. With &lt;code&gt;/mapeador&lt;/code&gt;, one command does all of this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/mapeador "ephemeral urban art documentation" B
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Calls &lt;code&gt;GET /autores?tema=...&lt;/code&gt; — maps the key authors and schools of thought&lt;/li&gt;
&lt;li&gt;Calls &lt;code&gt;GET /debate?tema=...&lt;/code&gt; — surfaces competing positions&lt;/li&gt;
&lt;li&gt;Calls &lt;code&gt;GET /search?q=...&amp;amp;top_k=20&lt;/code&gt; with two different query formulations&lt;/li&gt;
&lt;li&gt;Calls &lt;code&gt;POST /consulta&lt;/code&gt; twice with methodologically distinct questions&lt;/li&gt;
&lt;li&gt;Synthesizes all results into &lt;code&gt;mapa-corpus-&amp;lt;slug&amp;gt;.md&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Output structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Corpus Map — Ephemeral Urban Art Documentation&lt;/span&gt;

&lt;span class="gu"&gt;## Key Authors&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Brighenti (2010) — territoriality and ephemerality
&lt;span class="p"&gt;-&lt;/span&gt; Iveson (2010) — public space and street art legitimacy
...

&lt;span class="gu"&gt;## Academic Debate&lt;/span&gt;
Position A: Documentation preserves — [corpus evidence]
Position B: Documentation alters meaning — [corpus evidence]
...

&lt;span class="gu"&gt;## Evidence Bank (top 20 sources)&lt;/span&gt;
| citation_apa | relevance_score | research_hint |
|---|---|---|
...

&lt;span class="gu"&gt;## State of the Art Synthesis&lt;/span&gt;
[Generated by Ollama via /consulta — 400-600 words, cited]

&lt;span class="gu"&gt;## Identified Gaps&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; [PENDING — no corpus support]: ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This takes about 3 minutes and replaces what used to be 45–90 minutes of manual API work.&lt;/p&gt;

&lt;h3&gt;
  
  
  The &lt;code&gt;/auditor&lt;/code&gt; Agent — Zero Hallucinations Guarantee
&lt;/h3&gt;

&lt;p&gt;After any document is written, &lt;code&gt;/auditor&lt;/code&gt; runs through every substantive claim and classifies it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/auditor propuestas/minciencias/2026-grafpin/propuesta.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Audit — 2026-05-10&lt;/span&gt;

| Claim | Endpoint Checked | Status | Note |
|---|---|---|---|
| "Street art is recognized as intangible cultural heritage in 12 countries" | /search?q=intangible cultural heritage street art | [✗ PENDING] | No corpus support for "12 countries" |
| "Brighenti (2010) argues ephemerality is constitutive..." | /fragmentos?concepto=ephemeral constitutive meaning | [✓ VERIFIED] | relevance_score: 0.91, page 47 |
| "Computer vision achieves 87% accuracy in graffiti style detection" | /search?q=computer vision graffiti accuracy | [⚠ WEAK] | One source, pre-2018 |
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rule: if more than 40% of claims are &lt;code&gt;[✗ PENDING]&lt;/code&gt;, the document doesn't ship. This single constraint eliminates hallucination from the research output.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 4 — Multi-Query RAG Strategy
&lt;/h2&gt;

&lt;p&gt;One underrated technique in this system: &lt;strong&gt;always formulate 3–4 query variants&lt;/strong&gt; before calling &lt;code&gt;/consulta&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The same concept produces very different corpus results depending on phrasing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;queries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ephemeral art documentation methods&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;           &lt;span class="c1"&gt;# EN — technical angle
&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;documentación arte urbano efímero patrimonio&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# ES — heritage angle
&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;street art preservation digital archive&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;       &lt;span class="c1"&gt;# EN — infrastructure angle
&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;graffiti documentation urban memory loss&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;       &lt;span class="c1"&gt;# EN — urgency angle
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each formulation retrieves a different subset of the corpus. The agent layer handles this automatically — &lt;code&gt;/mapeador&lt;/code&gt; uses two &lt;code&gt;/search&lt;/code&gt; calls and two &lt;code&gt;/consulta&lt;/code&gt; calls with different formulations, then merges the evidence.&lt;/p&gt;

&lt;p&gt;The practical impact: query coverage increases from ~65% (single query) to ~92% (four-query merge) for complex topics.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 5 — Why This Applies to Any Domain
&lt;/h2&gt;

&lt;p&gt;The urban art corpus is just one instantiation. The architecture generalizes completely:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;What to change for a new domain&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;PDF corpus&lt;/td&gt;
&lt;td&gt;Replace with domain PDFs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Thematic categories&lt;/td&gt;
&lt;td&gt;Redefine &lt;code&gt;categoria_tematica&lt;/code&gt; for your taxonomy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ollama relevance prompt&lt;/td&gt;
&lt;td&gt;Update to score relevance to the new domain&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Agent prompts&lt;/td&gt;
&lt;td&gt;Update the research questions in each slash command&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API filters&lt;/td&gt;
&lt;td&gt;Add domain-specific facets (e.g., &lt;code&gt;species&lt;/code&gt;, &lt;code&gt;jurisdiction&lt;/code&gt;, &lt;code&gt;drug_class&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;I've seen this pattern applied to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Legal research&lt;/strong&gt;: case law corpora with jurisdiction and year filters&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Medical literature&lt;/strong&gt;: clinical trial PDFs with PICO-structure extraction&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Policy analysis&lt;/strong&gt;: government documents with agency and date filters&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key insight is that &lt;strong&gt;domain specificity is a feature, not a limitation&lt;/strong&gt;. A general-purpose RAG system optimized for everything is often not great at any one thing. A corpus built around a specific domain, with relevance scoring tuned to that domain, produces dramatically better retrieval.&lt;/p&gt;




&lt;h2&gt;
  
  
  Challenges and Lessons Learned
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Chunk size is a first-class design decision
&lt;/h3&gt;

&lt;p&gt;Too small (&amp;lt; 200 tokens): loses context, retrieval precision drops.&lt;br&gt;
Too large (&amp;gt; 700 tokens): embeds multiple ideas, relevance scores become noisy.&lt;br&gt;
The sweet spot for academic text: 400–512 tokens with paragraph boundary alignment.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Pre-compute expensive operations at ingestion time
&lt;/h3&gt;

&lt;p&gt;Running Ollama at query time for every search would make the system unusable. Pre-computing &lt;code&gt;relevancia&lt;/code&gt; and &lt;code&gt;research_hint&lt;/code&gt; at ingestion means query-time latency stays under 200ms for &lt;code&gt;/search&lt;/code&gt; and under 8 seconds for the full &lt;code&gt;/consulta&lt;/code&gt; RAG pipeline.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. The citation must be traceable to a page
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;citation_apa&lt;/code&gt; without &lt;code&gt;page&lt;/code&gt; and &lt;code&gt;doc_id&lt;/code&gt; is not an academic citation — it's a claim. Storing both means every output of the system can be verified by opening the original PDF.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Agents need failure modes, not just success paths
&lt;/h3&gt;

&lt;p&gt;When the corpus doesn't support a claim, the agents mark it &lt;code&gt;[PENDING]&lt;/code&gt; rather than hallucinating support. This requires explicit prompting: &lt;em&gt;"if you cannot find corpus evidence, write [PENDING — verify corpus] and do not fabricate a source."&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Multi-language corpora need language-aware retrieval
&lt;/h3&gt;

&lt;p&gt;Embedding models trained primarily on English produce lower-quality embeddings for Spanish and Portuguese text. Using &lt;code&gt;nomic-embed-text&lt;/code&gt; (multilingual-capable) and adding language filters (&lt;code&gt;idioma&lt;/code&gt; field) to all queries significantly improves cross-language retrieval.&lt;/p&gt;




&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;p&gt;Since deploying this system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Zero hallucinated citations&lt;/strong&gt; in output documents (validated by &lt;code&gt;/auditor&lt;/code&gt; on every deliverable)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Research proposal drafts in 3–4 hours&lt;/strong&gt; vs. 2–3 days manually&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Evidence density&lt;/strong&gt;: 1.8 citations per paragraph on average (up from ~0.4 with manual research)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Corpus growth&lt;/strong&gt;: The system accepts new PDFs at any time — ingestion takes ~30 seconds per document&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;A few things on the roadmap:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Citation graph&lt;/strong&gt;: linking documents by shared references to surface clusters of highly-cited foundational work&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Temporal drift detection&lt;/strong&gt;: alerting when a claim that was &lt;code&gt;[✓ VERIFIED]&lt;/code&gt; against the corpus in 2024 now has contradicting evidence from 2025+ additions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-corpus queries&lt;/strong&gt;: combining this corpus with data from the Grafpin platform itself (geolocated urban art documentation) to answer questions that require both academic literature and empirical field data&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Core Idea
&lt;/h2&gt;

&lt;p&gt;The goal was never to automate research. It was to make the evidence layer of research reliable.&lt;/p&gt;

&lt;p&gt;LLMs are extraordinary at synthesis, argument construction, and adapting tone for different audiences. They are unreliable as bibliographic databases. The solution isn't to avoid LLMs — it's to give them a trustworthy, queryable knowledge base so they can focus on what they're actually good at.&lt;/p&gt;

&lt;p&gt;A domain-specific RAG corpus, properly indexed and exposed through a well-designed API, changes the LLM's role from &lt;em&gt;source of truth&lt;/em&gt; to &lt;em&gt;engine of reasoning&lt;/em&gt;. That's a much better place for both the model and the researcher to be.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;The system described here is operational and actively used for academic research on urban art preservation. The platform it supports, &lt;a href="https://grafpin.com" rel="noopener noreferrer"&gt;Grafpin&lt;/a&gt;, documents geolocated street art in cities across Latin America.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Stack: Python · FastAPI · ChromaDB · MariaDB · Ollama · Claude Code · pdfplumber&lt;/em&gt;&lt;/p&gt;

</description>
      <category>rag</category>
      <category>ollama</category>
      <category>chromadb</category>
      <category>aiagents</category>
    </item>
    <item>
      <title>Building Software with AI Orchestration: A Spec-Driven and Memory-Enhanced Development Model</title>
      <dc:creator>sep83</dc:creator>
      <pubDate>Wed, 01 Apr 2026 13:22:56 +0000</pubDate>
      <link>https://dev.to/sep83/building-software-with-ai-orchestration-a-spec-driven-and-memory-enhanced-development-model-46fg</link>
      <guid>https://dev.to/sep83/building-software-with-ai-orchestration-a-spec-driven-and-memory-enhanced-development-model-46fg</guid>
      <description>&lt;h2&gt;
  
  
  Spec-Driven Development in the Age of AI
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;How Orchestrated Agents, Memory Systems, and Specification-First Thinking Are Transforming Software Engineering&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Software development is undergoing the most significant transformation since the invention of high-level languages.&lt;/p&gt;

&lt;p&gt;What once depended on manual coding and human memory is becoming a &lt;strong&gt;specification-driven, AI-assisted, memory-orchestrated workflow&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
In this model, the developer is no longer the primary writer of code but &lt;strong&gt;the author of logic&lt;/strong&gt;, while AI generates predictable, structured, architecture-compliant implementations.&lt;/p&gt;

&lt;p&gt;This article summarizes the development model I use today in production systems—an ecosystem built on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Specification-driven development (SDD)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Multi-agent AI orchestration&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Persistent project memory&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Architecture-aware code generation&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Human-led reasoning instead of manual typing&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1. The Core Shift: From Coding to Writing Specifications
&lt;/h2&gt;

&lt;p&gt;Traditional development used to follow this pattern:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Write code → Test → Fix → Rewrite → Document.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But now, it looks more like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Describe what must exist → The system generates it.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This shift happened because modern AI systems can produce:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cleaner code&lt;/li&gt;
&lt;li&gt;More consistent architecture&lt;/li&gt;
&lt;li&gt;Faster iterations&lt;/li&gt;
&lt;li&gt;Strict rule compliance&lt;/li&gt;
&lt;li&gt;Fewer human errors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our role changed from writing syntax to &lt;strong&gt;writing intent&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Today, we write:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Requirements
&lt;/li&gt;
&lt;li&gt;Acceptance criteria
&lt;/li&gt;
&lt;li&gt;Data structures
&lt;/li&gt;
&lt;li&gt;Architectural constraints
&lt;/li&gt;
&lt;li&gt;Process flows
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the AI transforms those specifications into working code.&lt;/p&gt;

&lt;p&gt;We are no longer “coding”—we are &lt;strong&gt;engineering logic&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. The Orchestrator: The Brain That Coordinates AI Agents
&lt;/h2&gt;

&lt;p&gt;At the center of this development model is an &lt;strong&gt;orchestrator agent&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
a coordinator that determines &lt;em&gt;when&lt;/em&gt; and &lt;em&gt;how&lt;/em&gt; other agents should act.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example Orchestration Flow
&lt;/h3&gt;

&lt;p&gt;Orchestrator&lt;br&gt;
├── DB Agent — explores schema, creates SQL, validates identifiers&lt;br&gt;
├── Architecture Agent — designs layers, workflows, ViewModels, endpoints&lt;br&gt;
├── Code Agent — generates code according to the approved design&lt;br&gt;
└── Reviewer Agent — performs adversarial auditing before completion&lt;/p&gt;

&lt;p&gt;Each agent has a scoped responsibility.&lt;br&gt;&lt;br&gt;
No single agent makes decisions outside its domain.&lt;br&gt;&lt;br&gt;
The orchestrator enforces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Order of execution
&lt;/li&gt;
&lt;li&gt;Architectural rules
&lt;/li&gt;
&lt;li&gt;Boundaries and permissions
&lt;/li&gt;
&lt;li&gt;Required approvals
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This eliminates chaos and ensures &lt;strong&gt;predictable automation&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Memory Systems: The Backbone of Long-Term Consistency
&lt;/h2&gt;

&lt;p&gt;Human memory cannot maintain the full state of a system with multiple modules, databases, and cross-cutting rules.&lt;/p&gt;

&lt;p&gt;AI memory systems solve this.&lt;/p&gt;

&lt;p&gt;Persistent memory stores:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Architectural decisions
&lt;/li&gt;
&lt;li&gt;Database mappings
&lt;/li&gt;
&lt;li&gt;Context about modules
&lt;/li&gt;
&lt;li&gt;Business rules
&lt;/li&gt;
&lt;li&gt;Naming conventions
&lt;/li&gt;
&lt;li&gt;Patterns and anti-patterns
&lt;/li&gt;
&lt;li&gt;Constraints introduced weeks or months earlier
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This ensures the AI always has the context needed to remain consistent.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why memory matters:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No repeated explanations&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No architectural drift&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stable reasoning across long development cycles&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automatic recall of rules and conventions&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Memory turns AI into a reliable engineering partner—not just a stateless tool.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Specification-Driven Development (SDD)
&lt;/h2&gt;

&lt;p&gt;Everything generated by the system begins with a &lt;strong&gt;specification&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;Requirement → Use Case → Architecture → Implementation → Review&lt;/p&gt;

&lt;p&gt;The system follows rules such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A feature cannot be implemented without a Use Case.&lt;/li&gt;
&lt;li&gt;Every Use Case must include acceptance criteria.&lt;/li&gt;
&lt;li&gt;Architecture must be produced before code generation.&lt;/li&gt;
&lt;li&gt;All generated code must trace back to the spec.&lt;/li&gt;
&lt;li&gt;Deviations require explicit classification:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;[TECH-ADJUST YYYY-MM-DD]&lt;/p&gt;

&lt;p&gt;This creates &lt;strong&gt;auditable development&lt;/strong&gt;, where every feature has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Purpose
&lt;/li&gt;
&lt;li&gt;Scope
&lt;/li&gt;
&lt;li&gt;Rules
&lt;/li&gt;
&lt;li&gt;Acceptance criteria
&lt;/li&gt;
&lt;li&gt;Implementation map
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is crucial for government systems, enterprise workflows, and large multi-team projects.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. AI-Generated Code: High Quality by Default
&lt;/h2&gt;

&lt;p&gt;In this model, the human no longer writes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Controllers
&lt;/li&gt;
&lt;li&gt;SQL queries
&lt;/li&gt;
&lt;li&gt;Entities
&lt;/li&gt;
&lt;li&gt;ViewModels
&lt;/li&gt;
&lt;li&gt;Services
&lt;/li&gt;
&lt;li&gt;Validations
&lt;/li&gt;
&lt;li&gt;Data access code
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;architecture agent&lt;/strong&gt; defines the structure.
&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;code agent&lt;/strong&gt; generates the implementation.
&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;reviewer agent&lt;/strong&gt; validates compliance.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All code follows rules like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Consistent naming
&lt;/li&gt;
&lt;li&gt;Layered architecture
&lt;/li&gt;
&lt;li&gt;Bounded contexts
&lt;/li&gt;
&lt;li&gt;Separation of concerns
&lt;/li&gt;
&lt;li&gt;Mandatory patterns for DB access
&lt;/li&gt;
&lt;li&gt;Approved conventions
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AI-generated code becomes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Predictable
&lt;/li&gt;
&lt;li&gt;Maintainable
&lt;/li&gt;
&lt;li&gt;Documentation-aligned
&lt;/li&gt;
&lt;li&gt;Easier to audit
&lt;/li&gt;
&lt;li&gt;Faster to evolve
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  6. Why This Model Works
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ✔️ Consistency
&lt;/h3&gt;

&lt;p&gt;Everything follows one architecture, one rule set, one direction.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✔️ Speed
&lt;/h3&gt;

&lt;p&gt;Features that took days are now done in hours.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✔️ Quality
&lt;/h3&gt;

&lt;p&gt;Architecture violations become nearly impossible.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✔️ Traceability
&lt;/h3&gt;

&lt;p&gt;You always know &lt;em&gt;why&lt;/em&gt; something exists.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✔️ Scalability
&lt;/h3&gt;

&lt;p&gt;This model scales across large systems with multiple modules and databases.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✔️ Human Evolution
&lt;/h3&gt;

&lt;p&gt;Developers become analysts, architects, and authors—not typists.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. The New Developer Skill Set
&lt;/h2&gt;

&lt;p&gt;In this new era, developers must excel at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Writing precise specifications
&lt;/li&gt;
&lt;li&gt;Structuring requirements
&lt;/li&gt;
&lt;li&gt;Designing data flows
&lt;/li&gt;
&lt;li&gt;Thinking architecturally
&lt;/li&gt;
&lt;li&gt;Reviewing AI output critically
&lt;/li&gt;
&lt;li&gt;Managing automated agents
&lt;/li&gt;
&lt;li&gt;Documenting reasoning
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your value is no longer measured by “lines of code,”&lt;br&gt;&lt;br&gt;
but by &lt;strong&gt;clarity of thought&lt;/strong&gt; and &lt;strong&gt;quality of technical instructions&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. Conclusion — A New Era of Software Engineering
&lt;/h2&gt;

&lt;p&gt;We are moving from:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Manual coding → Automated generation&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Developers as coders → Developers as writers and architects&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Ad-hoc memory → Persistent project memory&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Single-model prompting → Multi-agent orchestration&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is not theoretical.&lt;br&gt;&lt;br&gt;
This is the workflow I use daily in real industrial systems, involving multi-module architectures, government databases, validation flows, and large-scale project structures.&lt;/p&gt;

&lt;p&gt;AI now builds the code.&lt;br&gt;&lt;br&gt;
We build the &lt;strong&gt;rules, the intentions, and the architecture&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This collaboration produces software that is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Faster to build
&lt;/li&gt;
&lt;li&gt;Easier to maintain
&lt;/li&gt;
&lt;li&gt;More robust
&lt;/li&gt;
&lt;li&gt;More auditable
&lt;/li&gt;
&lt;li&gt;More consistent
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Welcome to the new reality:&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Developers are writers. Machines are builders.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>developers</category>
      <category>documentation</category>
    </item>
    <item>
      <title>Spec-Driven Development and Prompt Engineering: New Terms, Same Foundations?</title>
      <dc:creator>sep83</dc:creator>
      <pubDate>Sat, 21 Mar 2026 02:47:49 +0000</pubDate>
      <link>https://dev.to/sep83/spec-driven-development-and-prompt-engineering-new-terms-same-foundations-55j</link>
      <guid>https://dev.to/sep83/spec-driven-development-and-prompt-engineering-new-terms-same-foundations-55j</guid>
      <description>&lt;p&gt;In recent years, terms like &lt;em&gt;"spec-driven development"&lt;/em&gt; and &lt;em&gt;"prompt&lt;br&gt;
engineering"&lt;/em&gt; have gained popularity alongside the rise of AI-assisted&lt;br&gt;
coding tools. They are often presented as new paradigms that redefine&lt;br&gt;
how software is built. However, a closer look reveals that these&lt;br&gt;
concepts are not entirely new---they are, in many ways, a continuation&lt;br&gt;
of long-established practices under different names.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Core Idea Has Always Existed
&lt;/h2&gt;

&lt;p&gt;At the heart of software development has always been a simple principle:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Define &lt;em&gt;what&lt;/em&gt; the system should do before deciding &lt;em&gt;how&lt;/em&gt; to implement&lt;br&gt;
it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This principle is embodied in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Requirements engineering&lt;/li&gt;
&lt;li&gt;  Software design methodologies&lt;/li&gt;
&lt;li&gt;  Model-driven development&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The idea of writing structured specifications and refining them&lt;br&gt;
iteratively is not new. It has been a foundational part of software&lt;br&gt;
engineering for decades.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Has Actually Changed?
&lt;/h2&gt;

&lt;p&gt;The real shift is not in the methodology, but in execution.&lt;/p&gt;

&lt;p&gt;Traditionally:&lt;/p&gt;

&lt;p&gt;Human → Requirements → Code → Software&lt;/p&gt;

&lt;p&gt;Today, with AI:&lt;/p&gt;

&lt;p&gt;Human → Specifications → AI → Code → Software&lt;/p&gt;

&lt;p&gt;The difference lies in &lt;strong&gt;who writes the code&lt;/strong&gt;. The machine now performs&lt;br&gt;
a task that previously required significant human effort.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Rise of "Prompt Engineering"
&lt;/h2&gt;

&lt;p&gt;The term &lt;em&gt;prompt engineering&lt;/em&gt; suggests a new engineering discipline.&lt;br&gt;
However, in practice, it often refers to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Writing clear and structured instructions&lt;/li&gt;
&lt;li&gt;  Iterating on inputs to improve outputs&lt;/li&gt;
&lt;li&gt;  Understanding system behavior through experimentation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These activities resemble:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Technical writing&lt;/li&gt;
&lt;li&gt;  Requirements refinement&lt;/li&gt;
&lt;li&gt;  Interface interaction design&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While they require skill, calling them "engineering" may stretch the&lt;br&gt;
traditional definition of the term.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is It Really Engineering?
&lt;/h2&gt;

&lt;p&gt;Engineering typically implies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  A strong theoretical foundation&lt;/li&gt;
&lt;li&gt;  Systematic methodologies&lt;/li&gt;
&lt;li&gt;  Application of scientific and mathematical principles&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not every structured activity qualifies as engineering. We do not refer&lt;br&gt;
to tasks like procurement or observation as engineering, even if they&lt;br&gt;
involve processes and optimization.&lt;/p&gt;

&lt;p&gt;By that standard, labeling every interaction with AI as "engineering"&lt;br&gt;
risks diluting the meaning of the term.&lt;/p&gt;

&lt;h2&gt;
  
  
  Spec-Driven Development ≠ New Paradigm
&lt;/h2&gt;

&lt;p&gt;"Spec-driven development" is often presented as a modern approach. In&lt;br&gt;
reality, it closely mirrors traditional requirements engineering, with&lt;br&gt;
one key difference:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The implementation phase is now automated.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The process itself---defining, refining, and validating&lt;br&gt;
requirements---remains unchanged.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Role of AI: Acceleration, Not Reinvention
&lt;/h2&gt;

&lt;p&gt;AI has dramatically reduced the time required to move from idea to&lt;br&gt;
implementation. Tasks that once took weeks can now be completed in&lt;br&gt;
minutes.&lt;/p&gt;

&lt;p&gt;However, this acceleration does not fundamentally alter the development&lt;br&gt;
lifecycle. It enhances it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Looking Ahead
&lt;/h2&gt;

&lt;p&gt;As AI systems evolve, they may:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Understand context more deeply&lt;/li&gt;
&lt;li&gt;  Infer intent with minimal input&lt;/li&gt;
&lt;li&gt;  Reduce the need for explicit specifications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If that happens, even current practices like prompt engineering and&lt;br&gt;
spec-driven development may become obsolete.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;The emergence of new terminology often reflects shifts in tools rather&lt;br&gt;
than in core principles. While AI has transformed how quickly software&lt;br&gt;
can be built, it has not replaced the foundational need for clear&lt;br&gt;
requirements.&lt;/p&gt;

&lt;p&gt;In that sense, &lt;em&gt;spec-driven development&lt;/em&gt; is less a revolution and more&lt;br&gt;
an evolution---one that automates implementation but leaves the&lt;br&gt;
underlying discipline intact.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>architecture</category>
      <category>developer</category>
    </item>
    <item>
      <title>Beyond RBAC: Designing Scalable Access Control Without Role Explosion</title>
      <dc:creator>sep83</dc:creator>
      <pubDate>Sun, 15 Feb 2026 17:08:14 +0000</pubDate>
      <link>https://dev.to/sep83/beyond-rbac-designing-scalable-access-control-without-role-explosion-770</link>
      <guid>https://dev.to/sep83/beyond-rbac-designing-scalable-access-control-without-role-explosion-770</guid>
      <description>&lt;p&gt;Role-Based Access Control (RBAC) is often the first authorization model developers reach for—and for good reason. It is simple, intuitive, and easy to explain. But as systems evolve, RBAC frequently becomes a bottleneck rather than a solution.&lt;/p&gt;

&lt;p&gt;This article explores &lt;strong&gt;why traditional RBAC fails at scale&lt;/strong&gt;, compares it with other common authorization approaches, and presents a &lt;strong&gt;generalized hybrid pattern&lt;/strong&gt; that avoids role explosion while preserving clarity, flexibility, and auditability.&lt;/p&gt;

&lt;p&gt;The goal is not to replace RBAC, but to &lt;strong&gt;use it correctly&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Traditional RBAC: Strengths and Limits
&lt;/h2&gt;

&lt;p&gt;At its core, RBAC maps roles to permissions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ADMIN  → create, read, update, delete
EDITOR → create, read, update
VIEWER → read
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works well when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All users of a role behave the same way&lt;/li&gt;
&lt;li&gt;Permissions are uniform across resources&lt;/li&gt;
&lt;li&gt;The system is small or single-tenant&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, RBAC quietly assumes something that rarely remains true:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A role fully defines what a user can do everywhere.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Once this assumption breaks, problems appear.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Role Explosion Problem
&lt;/h2&gt;

&lt;p&gt;As soon as permissions depend on &lt;strong&gt;context&lt;/strong&gt;, roles start multiplying:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Editor for project A&lt;/li&gt;
&lt;li&gt;Editor for project B&lt;/li&gt;
&lt;li&gt;Reviewer who can approve but not edit&lt;/li&gt;
&lt;li&gt;Viewer who can export but not modify&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each variation becomes a new role. Over time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Roles lose semantic meaning&lt;/li&gt;
&lt;li&gt;Authorization becomes harder to reason about&lt;/li&gt;
&lt;li&gt;Changes require migrations instead of configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This phenomenon is known as &lt;strong&gt;role explosion&lt;/strong&gt;, and it is the most common failure mode of RBAC.&lt;/p&gt;




&lt;h2&gt;
  
  
  Common Alternatives (And Why They Struggle)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  RBAC with Custom Logic
&lt;/h3&gt;

&lt;p&gt;A frequent workaround is adding conditional checks in code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;role allows action
AND resource belongs to user
AND state is valid
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach works short-term, but:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authorization logic becomes scattered&lt;/li&gt;
&lt;li&gt;Rules are implicit and hard to audit&lt;/li&gt;
&lt;li&gt;Behavior depends on code paths, not data&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Attribute-Based Access Control (ABAC)
&lt;/h3&gt;

&lt;p&gt;ABAC evaluates policies based on attributes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;user.department == resource.department
AND user.level &amp;gt;= resource.required_level
AND action in allowed_actions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ABAC is powerful, but often:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hard to debug&lt;/li&gt;
&lt;li&gt;Hard to explain&lt;/li&gt;
&lt;li&gt;Easy to over-engineer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It shines in policy-heavy environments, but is excessive for many applications.&lt;/p&gt;




&lt;h3&gt;
  
  
  Access Control Lists (ACLs)
&lt;/h3&gt;

&lt;p&gt;ACLs attach permissions directly to resources:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Resource X:
  User A → read, edit
  User B → read
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;They provide excellent granularity, but:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scale poorly with many users&lt;/li&gt;
&lt;li&gt;Make global permission reasoning difficult&lt;/li&gt;
&lt;li&gt;Lack a clear notion of user capability&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  A Balanced Pattern: Capability vs Scope
&lt;/h2&gt;

&lt;p&gt;A more scalable approach separates &lt;strong&gt;capability&lt;/strong&gt; from &lt;strong&gt;scope&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Core Principle
&lt;/h3&gt;

&lt;p&gt;Access is granted only if &lt;strong&gt;both&lt;/strong&gt; conditions are true:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Access = Role allows action
      AND Assignment grants action on resource
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a &lt;strong&gt;conjunctive authorization model&lt;/strong&gt; that is strict, flexible, and auditable.&lt;/p&gt;




&lt;h2&gt;
  
  
  Roles as Capability Ceilings
&lt;/h2&gt;

&lt;p&gt;Roles answer one question only:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;What types of actions can this user ever perform?&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;They are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Global&lt;/li&gt;
&lt;li&gt;Few in number&lt;/li&gt;
&lt;li&gt;Stable over time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Roles should &lt;strong&gt;not&lt;/strong&gt; encode:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resource ownership&lt;/li&gt;
&lt;li&gt;Project membership&lt;/li&gt;
&lt;li&gt;Temporary responsibilities&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They define a &lt;strong&gt;maximum authority&lt;/strong&gt;, not actual access.&lt;/p&gt;




&lt;h2&gt;
  
  
  Assignments as the Granularity Layer
&lt;/h2&gt;

&lt;p&gt;Fine-grained permissions are handled through explicit assignments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bound to a specific user&lt;/li&gt;
&lt;li&gt;Bound to a specific resource&lt;/li&gt;
&lt;li&gt;Containing an explicit list of allowed actions&lt;/li&gt;
&lt;li&gt;Optionally enriched with metadata (who assigned it, status, expiration)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Assignments answer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;What is this user allowed to do here?&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The same user can have different permissions on different resources—without changing roles.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Pattern Scales
&lt;/h2&gt;

&lt;h3&gt;
  
  
  No Role Explosion
&lt;/h3&gt;

&lt;p&gt;New requirements create new assignments, not new roles.&lt;/p&gt;

&lt;h3&gt;
  
  
  Built-in Separation of Duties
&lt;/h3&gt;

&lt;p&gt;If a role cannot approve, no assignment can override that.&lt;/p&gt;

&lt;h3&gt;
  
  
  Clear Audit Trail
&lt;/h3&gt;

&lt;p&gt;Every permission is explicit, inspectable, and traceable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Simpler Mental Model
&lt;/h3&gt;

&lt;p&gt;Roles define &lt;strong&gt;potential&lt;/strong&gt;, assignments define &lt;strong&gt;reality&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Generic Authorization Flow
&lt;/h2&gt;

&lt;p&gt;A typical authorization check follows a predictable sequence:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Is the user in the correct context or boundary?&lt;/li&gt;
&lt;li&gt;Does the role allow this action type?&lt;/li&gt;
&lt;li&gt;Is there an assignment for this resource?&lt;/li&gt;
&lt;li&gt;Does the assignment include the action?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each step is independent, testable, and explainable.&lt;/p&gt;




&lt;h2&gt;
  
  
  When to Use This Pattern
&lt;/h2&gt;

&lt;p&gt;This model is a good fit when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Permissions vary per resource&lt;/li&gt;
&lt;li&gt;Users collaborate on subsets of shared data&lt;/li&gt;
&lt;li&gt;Separation of duties matters&lt;/li&gt;
&lt;li&gt;Auditability is required&lt;/li&gt;
&lt;li&gt;You want to avoid hardcoding rules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It may be unnecessary when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The system is small or single-tenant&lt;/li&gt;
&lt;li&gt;All users of a role behave identically&lt;/li&gt;
&lt;li&gt;Only a few permission levels exist&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Roles should express &lt;strong&gt;capability&lt;/strong&gt;, not scope
&lt;/li&gt;
&lt;li&gt;Granularity belongs in &lt;strong&gt;data&lt;/strong&gt;, not role names
&lt;/li&gt;
&lt;li&gt;Conjunctive authorization improves safety and clarity
&lt;/li&gt;
&lt;li&gt;Authorization rules should be auditable, not implicit
&lt;/li&gt;
&lt;li&gt;Design access control with growth in mind&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;em&gt;Good access control is not about more rules—it’s about clearer boundaries.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>security</category>
      <category>control</category>
      <category>backend</category>
    </item>
    <item>
      <title>Back to Lovelace: Software Without Unnecessary Abstractions</title>
      <dc:creator>sep83</dc:creator>
      <pubDate>Sun, 08 Feb 2026 18:04:24 +0000</pubDate>
      <link>https://dev.to/sep83/back-to-lovelace-software-without-unnecessary-abstractions-407a</link>
      <guid>https://dev.to/sep83/back-to-lovelace-software-without-unnecessary-abstractions-407a</guid>
      <description>&lt;h2&gt;
  
  
  A return to intentional code in the age of artificial intelligence
&lt;/h2&gt;

&lt;p&gt;For decades, software engineering has followed a trajectory that equates progress with layers: more frameworks, more abstractions, more automation hidden behind conventions. This trajectory was not accidental. It was a response to very real problems—growing teams, inconsistent coding practices, fragile systems, and the human cost of maintaining large codebases.&lt;/p&gt;

&lt;p&gt;But the context has changed.&lt;/p&gt;

&lt;p&gt;With the rise of artificial intelligence as an active participant in software development, many of the original reasons for heavy frameworks and runtime abstractions are no longer dominant. This article proposes a deliberate shift in perspective that I call &lt;strong&gt;“Back to Lovelace”&lt;/strong&gt;: a return to explicit, intentional, and minimal software design—augmented by AI, not obscured by it.&lt;/p&gt;




&lt;h2&gt;
  
  
  The original problem frameworks tried to solve
&lt;/h2&gt;

&lt;p&gt;In the early days of software, performance and correctness depended far more on &lt;em&gt;how&lt;/em&gt; code was written than on the language itself. A well-written program in a low-level or high-level language could be equally efficient. The real problem was never the language—it was inconsistency.&lt;/p&gt;

&lt;p&gt;As projects grew and teams expanded, individual styles and interpretations led to fragmentation. Frameworks emerged primarily as a &lt;strong&gt;social solution&lt;/strong&gt;, not a technical one. They imposed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;conventions,&lt;/li&gt;
&lt;li&gt;folder structures,&lt;/li&gt;
&lt;li&gt;lifecycle rules,&lt;/li&gt;
&lt;li&gt;and architectural patterns.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Frameworks created a shared mental model so teams could collaborate at scale. Performance and clarity were often sacrificed in favor of uniformity and governance.&lt;/p&gt;

&lt;p&gt;That tradeoff made sense—&lt;em&gt;then&lt;/em&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  AI changes the equation
&lt;/h2&gt;

&lt;p&gt;Artificial intelligence fundamentally alters the development process in a way we rarely acknowledge explicitly.&lt;/p&gt;

&lt;p&gt;AI does not improvise architecture. It executes instructions.&lt;/p&gt;

&lt;p&gt;Given clear rules, constraints, and intent, AI can generate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;consistent structure,&lt;/li&gt;
&lt;li&gt;repeatable patterns,&lt;/li&gt;
&lt;li&gt;readable and maintainable code,&lt;/li&gt;
&lt;li&gt;without personal bias or stylistic drift.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In other words, AI eliminates much of the human chaos that frameworks were designed to control.&lt;/p&gt;

&lt;p&gt;Today, the most valuable input is not a framework—it is a &lt;strong&gt;well-defined prompt&lt;/strong&gt; that encodes architectural intent.&lt;/p&gt;




&lt;h2&gt;
  
  
  Back to Lovelace: what the name means
&lt;/h2&gt;

&lt;p&gt;Ada Lovelace understood something fundamental long before modern software existed: machines do not create intent—humans do. Machines execute formalized ideas with precision.&lt;/p&gt;

&lt;p&gt;“Back to Lovelace” does not mean returning to primitive tools. It means returning to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;explicit logic,&lt;/li&gt;
&lt;li&gt;transparent execution,&lt;/li&gt;
&lt;li&gt;and intentional design.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AI becomes the executor of structure, not the source of abstraction.&lt;/p&gt;




&lt;h2&gt;
  
  
  Minimal standards instead of heavy frameworks
&lt;/h2&gt;

&lt;p&gt;The proposal is not an absence of structure. It is &lt;strong&gt;minimal, explicit structure&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Patterns such as MVC, MVVM, or layered architectures have existed for decades. They are not inventions of frameworks. Frameworks merely &lt;em&gt;codified&lt;/em&gt; them—often with additional runtime complexity.&lt;/p&gt;

&lt;p&gt;A minimal standard is enough:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/controllers
/services
/models
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Controllers handle transport and I/O
&lt;/li&gt;
&lt;li&gt;Services encapsulate business logic
&lt;/li&gt;
&lt;li&gt;Models represent domain data
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No magic. No reflection-heavy lifecycles. No hidden execution paths.&lt;/p&gt;

&lt;p&gt;AI-generated scaffolding can apply these conventions consistently without introducing runtime abstractions.&lt;/p&gt;




&lt;h2&gt;
  
  
  Scalability is an infrastructure problem, not a framework problem
&lt;/h2&gt;

&lt;p&gt;Modern scalability is achieved through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;container replication,&lt;/li&gt;
&lt;li&gt;load balancers,&lt;/li&gt;
&lt;li&gt;horizontal scaling,&lt;/li&gt;
&lt;li&gt;stateless services,&lt;/li&gt;
&lt;li&gt;observability and monitoring.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Duplicating a well-designed service across containers solves the majority of real-world scaling needs.&lt;/p&gt;

&lt;p&gt;Frameworks do not provide scalability. &lt;strong&gt;Infrastructure does.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If a system genuinely requires a radically different model—massive throughput, extreme latency constraints, or global distribution—it should be designed that way &lt;em&gt;from the beginning&lt;/em&gt;, not retrofitted through abstractions.&lt;/p&gt;




&lt;h2&gt;
  
  
  SQL as a first-class citizen
&lt;/h2&gt;

&lt;p&gt;One of the clearest casualties of over-abstraction has been the database layer.&lt;/p&gt;

&lt;p&gt;Explicit SQL:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;communicates intent clearly,&lt;/li&gt;
&lt;li&gt;exposes real relationships,&lt;/li&gt;
&lt;li&gt;is auditable and optimizable,&lt;/li&gt;
&lt;li&gt;reflects the true domain model.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even complex SQL tells a story. An experienced engineer can understand where data comes from, how it is transformed, and why it exists.&lt;/p&gt;

&lt;p&gt;ORMs, especially general-purpose runtime ORMs, often obscure this narrative. Views, stored procedures, and optimized queries become difficult or unnatural to express. The abstraction replaces the domain instead of serving it.&lt;/p&gt;

&lt;p&gt;In complex systems, this is not simplification—it is distortion.&lt;/p&gt;




&lt;h2&gt;
  
  
  The myth of constant migration
&lt;/h2&gt;

&lt;p&gt;Automatic migrations were designed for a time when changing database engines was common.&lt;/p&gt;

&lt;p&gt;That world no longer exists.&lt;/p&gt;

&lt;p&gt;Today we:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;choose a database engine deliberately,&lt;/li&gt;
&lt;li&gt;containerize it,&lt;/li&gt;
&lt;li&gt;and evolve schemas incrementally.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Microservices and APIs further reduce the need for large-scale schema migrations. Services own their data. Interfaces, not schemas, define boundaries.&lt;/p&gt;

&lt;p&gt;Migration is now an exception—not a foundation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Typing is not abstraction—it is intent
&lt;/h2&gt;

&lt;p&gt;Strong typing does not hide behavior. It clarifies it.&lt;/p&gt;

&lt;p&gt;Types:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;define contracts,&lt;/li&gt;
&lt;li&gt;reduce ambiguity,&lt;/li&gt;
&lt;li&gt;guide both humans and AI,&lt;/li&gt;
&lt;li&gt;prevent entire classes of errors.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In an AI-assisted workflow, typing becomes even more valuable. It anchors generated code to explicit expectations.&lt;/p&gt;

&lt;p&gt;Typing aligns perfectly with the Back to Lovelace philosophy.&lt;/p&gt;




&lt;h2&gt;
  
  
  The decline of runtime ORMs
&lt;/h2&gt;

&lt;p&gt;Runtime ORMs introduce:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;latency,&lt;/li&gt;
&lt;li&gt;hidden queries,&lt;/li&gt;
&lt;li&gt;unpredictable performance,&lt;/li&gt;
&lt;li&gt;cognitive overhead.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They struggle with advanced database features such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;views,&lt;/li&gt;
&lt;li&gt;stored procedures,&lt;/li&gt;
&lt;li&gt;fine-grained optimization.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Modern systems benefit more from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;explicit SQL,&lt;/li&gt;
&lt;li&gt;query builders where appropriate,&lt;/li&gt;
&lt;li&gt;compile-time checks,&lt;/li&gt;
&lt;li&gt;and clear data boundaries.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ORMs are not inherently evil—but as default runtime layers, their relevance is fading.&lt;/p&gt;




&lt;h2&gt;
  
  
  Small systems, composed into large ones
&lt;/h2&gt;

&lt;p&gt;The future is not monolith versus microservices.&lt;/p&gt;

&lt;p&gt;The future is &lt;strong&gt;intentional composition&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;small services,&lt;/li&gt;
&lt;li&gt;clear APIs,&lt;/li&gt;
&lt;li&gt;explicit responsibilities,&lt;/li&gt;
&lt;li&gt;minimal abstractions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Serverless, microservices, and specialized APIs are not about fragmentation—they are about clarity.&lt;/p&gt;

&lt;p&gt;Large systems should emerge from the combination of simple, understandable parts.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion: progress through subtraction
&lt;/h2&gt;

&lt;p&gt;Back to Lovelace is not nostalgia.&lt;/p&gt;

&lt;p&gt;It is an acknowledgment that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AI reduces the need for human-enforced abstractions,&lt;/li&gt;
&lt;li&gt;clarity beats cleverness,&lt;/li&gt;
&lt;li&gt;infrastructure scales systems—not frameworks,&lt;/li&gt;
&lt;li&gt;and explicit code is easier to reason about than magical behavior.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The future of software is not more layers.&lt;/p&gt;

&lt;p&gt;It is fewer assumptions, clearer intent, and machines executing exactly what we mean.&lt;/p&gt;

&lt;p&gt;That is not regression.&lt;/p&gt;

&lt;p&gt;That is progress.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>ai</category>
      <category>programming</category>
      <category>softwareengineering</category>
    </item>
  </channel>
</rss>
