<?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: Michael Elian Kevin</title>
    <description>The latest articles on DEV Community by Michael Elian Kevin (@kevinkwee27).</description>
    <link>https://dev.to/kevinkwee27</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4055933%2Fb69a7145-385b-4b15-b565-8fd8a303aef1.png</url>
      <title>DEV Community: Michael Elian Kevin</title>
      <link>https://dev.to/kevinkwee27</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kevinkwee27"/>
    <language>en</language>
    <item>
      <title>How I Simplified My GitHub Copilot Agent Squad</title>
      <dc:creator>Michael Elian Kevin</dc:creator>
      <pubDate>Sun, 09 Aug 2026 05:42:35 +0000</pubDate>
      <link>https://dev.to/kevinkwee27/how-i-simplified-my-github-copilot-agent-squad-4i9i</link>
      <guid>https://dev.to/kevinkwee27/how-i-simplified-my-github-copilot-agent-squad-4i9i</guid>
      <description>&lt;p&gt;A while back I built &lt;strong&gt;GitHub Copilot Squad&lt;/strong&gt;, a custom multi-agent setup for the GitHub Copilot coding agent. After using it on real-world tasks, I rebuilt it into a simpler version. This is the story of what I tried, what I learned, and what I ended up with.&lt;/p&gt;

&lt;h2&gt;
  
  
  The first version: 4 agents
&lt;/h2&gt;

&lt;p&gt;The original idea was role separation. Don't let one agent plan, build, and review all at once. So I split it into four agents:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Capybara:&lt;/strong&gt; the router&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Otter:&lt;/strong&gt; the implementer&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Owl:&lt;/strong&gt; the reviewer&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Squirrel:&lt;/strong&gt; a lightweight helper for simple questions&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/kevinkwee" rel="noopener noreferrer"&gt;
        kevinkwee
      &lt;/a&gt; / &lt;a href="https://github.com/kevinkwee/github-copilot-squad" rel="noopener noreferrer"&gt;
        github-copilot-squad
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Custom multi-agent orchestration for GitHub Copilot coding agent with role-based routing.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;GitHub Copilot Squad&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;A custom multi-agent orchestration setup for &lt;strong&gt;GitHub Copilot coding agent&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;This repo defines a 4-agent team with clear roles:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Capybara&lt;/strong&gt;: router/orchestrator&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Otter&lt;/strong&gt;: implementation agent&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Owl&lt;/strong&gt;: reviewer/QA gate&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Squirrel&lt;/strong&gt;: general assistant for simple/non-technical requests&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The goal is to separate execution and review, so technical tasks go through an implementation + review loop before final output, with different models contributing different perspectives.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Why this exists&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;When using one agent for everything, prompts often mix planning, coding, and reviewing in one pass, and the context window can fill up quickly. This setup enforces role separation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Technical work is done by a builder agent (&lt;code&gt;Otter&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Quality is validated by a strict reviewer (&lt;code&gt;Owl&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Implementation and review can run on different models, giving a multi-perspective quality check&lt;/li&gt;
&lt;li&gt;Non-technical/simple requests are handled fast by a lightweight helper (&lt;code&gt;Squirrel&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Routing and iteration control…&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/kevinkwee/github-copilot-squad" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;The goal was to keep implementation and review as separate perspectives, so technical work goes through a build-then-review loop before it comes back to you.&lt;/p&gt;

&lt;h3&gt;
  
  
  What using it taught me
&lt;/h3&gt;

&lt;p&gt;The separation sounded clean on paper. In practice, a few things bugged me:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A separate generalist implementer didn't add much.&lt;/strong&gt; Spinning up a separate agent just to offload execution only pays off when that agent is specialized (a frontend expert, a specific-framework expert). My &lt;code&gt;Otter&lt;/code&gt; was a generalist, just like &lt;code&gt;Capybara&lt;/code&gt;. Two generalists gave me handoff overhead, not more perspective.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A fresh isolated context per request is expensive.&lt;/strong&gt; Because &lt;code&gt;Otter&lt;/code&gt; was a separate sub-agent, every request started in a fresh context. That meant more tokens and more time for it to re-read the codebase and re-analyze the problem, even for follow-ups that built directly on the previous work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The context-window fear was overblown.&lt;/strong&gt; My worry with merging the builder into the entry point was that the context window would fill up fast. After running it on real, multi-step tasks, it grew slower than I expected, and the benefit of warm, carry-over context outweighed the cost.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I built a simpler version.&lt;/p&gt;




&lt;h2&gt;
  
  
  The simplified version
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/kevinkwee" rel="noopener noreferrer"&gt;
        kevinkwee
      &lt;/a&gt; / &lt;a href="https://github.com/kevinkwee/github-copilot-squad-simplified" rel="noopener noreferrer"&gt;
        github-copilot-squad-simplified
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Simplified version of my GitHub Copilot Squad, a custom multi-agent orchestration for GitHub Copilot coding agent with role-based routing.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;GitHub Copilot Squad (Simplified)&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;A simplified orchestration setup for the &lt;strong&gt;GitHub Copilot coding agent&lt;/strong&gt;, and a leaner variant of &lt;a href="https://github.com/kevinkwee/github-copilot-squad" rel="noopener noreferrer"&gt;github-copilot-squad&lt;/a&gt;. It ships in two modes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Trio (default)&lt;/strong&gt;: &lt;code&gt;Capybara&lt;/code&gt; (entry point + implementer) + &lt;code&gt;Owl&lt;/code&gt; (code reviewer) + &lt;code&gt;Cat&lt;/code&gt; (comment/docstring reviewer).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Duo&lt;/strong&gt;: &lt;code&gt;Capybara&lt;/code&gt; + &lt;code&gt;Owl&lt;/code&gt; only, with no dedicated comment/docstring pass. The Duo behavior lives in &lt;code&gt;CapybaraDuo.agent.md&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In both modes the goal is the same: keep implementation and review as &lt;strong&gt;separate perspectives&lt;/strong&gt;, so technical work goes through a build → review loop before final output. What's removed (vs the original 4-agent squad) is the overhead of a separate execution agent and a separate lightweight helper.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Why this simplified version exists&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;The original squad offloads implementation to a dedicated builder agent (&lt;code&gt;Otter&lt;/code&gt;), with &lt;code&gt;Capybara&lt;/code&gt; acting as a pure router. After using it on real-world tasks, that separation turned out to be &lt;strong&gt;unnecessary&lt;/strong&gt; for this…&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/kevinkwee/github-copilot-squad-simplified" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;I merged &lt;code&gt;Otter&lt;/code&gt; into &lt;code&gt;Capybara&lt;/code&gt;. Now &lt;code&gt;Capybara&lt;/code&gt; is the entry point &lt;strong&gt;and&lt;/strong&gt; the implementer. It receives the request, does the work, then hands off to &lt;code&gt;Owl&lt;/code&gt; for review. I also dropped &lt;code&gt;Squirrel&lt;/code&gt; &lt;em&gt;(tbh it was useless, I never really used it irl 😂)&lt;/em&gt;, so &lt;code&gt;Capybara&lt;/code&gt; handles simple questions directly. &lt;code&gt;Owl&lt;/code&gt; stayed as the reviewer.&lt;/p&gt;

&lt;p&gt;It ships in two modes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Duo&lt;/strong&gt;. &lt;code&gt;Capybara&lt;/code&gt; + &lt;code&gt;Owl&lt;/code&gt; (the lean version)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trio&lt;/strong&gt; (default). &lt;code&gt;Capybara&lt;/code&gt; + &lt;code&gt;Owl&lt;/code&gt; + &lt;code&gt;Cat&lt;/code&gt; (more on &lt;code&gt;Cat&lt;/code&gt; in a moment)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F85atl058hg0n0bgqgioo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F85atl058hg0n0bgqgioo.png" alt="Flowchart" width="798" height="227"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For technical requests, &lt;code&gt;Capybara&lt;/code&gt; implements, then loops with &lt;code&gt;Owl&lt;/code&gt; until &lt;code&gt;Owl&lt;/code&gt; approves. In Trio mode, it then loops with &lt;code&gt;Cat&lt;/code&gt; until &lt;code&gt;Cat&lt;/code&gt; approves, then returns the result.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo98i6jn5igsxd1bmhedm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo98i6jn5igsxd1bmhedm.png" alt="Sequence Diagram" width="800" height="908"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why I added a comment/docstring-only reviewer
&lt;/h3&gt;

&lt;p&gt;For a while, Duo mode was enough. But I noticed something: agents sometimes write unnecessary, redundant, or inappropriate comments and docstrings, even when the rules already say not to. &lt;code&gt;Owl&lt;/code&gt;'s review covers this, but &lt;code&gt;Owl&lt;/code&gt; also reviews the code implementation, so these prose issues sometimes got skipped.&lt;/p&gt;

&lt;p&gt;So I added &lt;strong&gt;&lt;code&gt;Cat&lt;/code&gt;&lt;/strong&gt;, a reviewer that focuses ONLY on comments and docstrings. It runs after &lt;code&gt;Owl&lt;/code&gt; approves, so the code is already correct. &lt;code&gt;Cat&lt;/code&gt;'s whole job is to groom the prose. Each review pass writes a report file, so there's a lightweight audit trail.&lt;/p&gt;

&lt;p&gt;That's the Trio mode: &lt;code&gt;Capybara&lt;/code&gt; and &lt;code&gt;Owl&lt;/code&gt; (code review), then &lt;code&gt;Capybara&lt;/code&gt; and &lt;code&gt;Cat&lt;/code&gt; (comment/docstring review), then finish.&lt;/p&gt;

&lt;h3&gt;
  
  
  One thing that's not there yet
&lt;/h3&gt;

&lt;p&gt;Both setups treat an &lt;code&gt;AGENTS.md&lt;/code&gt; file as the source of truth for project-specific rules (stack, test commands, linter, naming, and the expected comment/docstring rules). The agent profiles stay generic and reusable. The project-specific detail lives in &lt;code&gt;AGENTS.md&lt;/code&gt;, which is easier to update and maintain than editing the bundled agent profiles.&lt;/p&gt;

&lt;p&gt;I haven't published an &lt;code&gt;AGENTS.md&lt;/code&gt; example or template yet. I'll add one as soon as I have time to put a clean template together. Until then, you can write your own &lt;code&gt;AGENTS.md&lt;/code&gt; describing your stack, your test command, your linter, and any hard constraints you want the agents to respect.&lt;/p&gt;

&lt;h3&gt;
  
  
  The animals
&lt;/h3&gt;

&lt;p&gt;Because naming things is half the fun:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;th&gt;Animal&lt;/th&gt;
&lt;th&gt;Why it fits&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Entry point + Implementer&lt;/td&gt;
&lt;td&gt;Capybara 🦫&lt;/td&gt;
&lt;td&gt;Calm and sociable. Comfortable doing the work itself and coordinating the review.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Code reviewer&lt;/td&gt;
&lt;td&gt;Owl 🦉&lt;/td&gt;
&lt;td&gt;Sharp observation. Spots sneaky issues.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Comment/docstring reviewer&lt;/td&gt;
&lt;td&gt;Cat 🐱&lt;/td&gt;
&lt;td&gt;Fastidious groomer. Grooms comments and docstrings until every word earns its place.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;The short version: I started with 4 agents, found that one generalist implementer was enough, and ended up with a 2-agent setup with an optional 3rd for docstring grooming. The configs are just markdown agent profiles you can drop into VS Code Copilot Chat.&lt;/p&gt;





&lt;div class="ltag-offer"&gt;
  &lt;div class="ltag-offer__body"&gt; Find this useful? Smash the star on the repo! ⭐ &lt;/div&gt;
    &lt;a href="https://github.com/kevinkwee/github-copilot-squad-simplified" class="ltag-offer__button crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;Star on GitHub&lt;/a&gt;
&lt;/div&gt;


</description>
      <category>githubcopilot</category>
      <category>ai</category>
      <category>vscode</category>
      <category>productivity</category>
    </item>
    <item>
      <title>FckVer: A Practical Versioning Strategy for Odoo</title>
      <dc:creator>Michael Elian Kevin</dc:creator>
      <pubDate>Fri, 31 Jul 2026 04:46:30 +0000</pubDate>
      <link>https://dev.to/kevinkwee27/fckver-a-practical-versioning-strategy-for-odoo-4kfg</link>
      <guid>https://dev.to/kevinkwee27/fckver-a-practical-versioning-strategy-for-odoo-4kfg</guid>
      <description>&lt;h2&gt;
  
  
  FckVer: A Practical Versioning Strategy for Odoo
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Disclaimer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This article contains profanity. The naming is intentional. The idea started from a long debugging session with Odoo's module versioning. If you don't appreciate the name, feel free to rename it internally.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;

&lt;p&gt;Odoo has a single version field inside &lt;code&gt;__manifest__.py&lt;/code&gt;.&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="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;version&lt;/span&gt;&lt;span class="sh"&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;18.0.1.0.0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple?&lt;/p&gt;

&lt;p&gt;Not really.&lt;/p&gt;

&lt;p&gt;That single version is expected to represent several completely different concepts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;application version&lt;/li&gt;
&lt;li&gt;module version&lt;/li&gt;
&lt;li&gt;migration version&lt;/li&gt;
&lt;li&gt;deployment ordering&lt;/li&gt;
&lt;li&gt;upgrade detection&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In reality, these are different things.&lt;/p&gt;

&lt;p&gt;Coming from ecosystems like Django, Rails, Alembic, Flyway or Liquibase, this felt strange because those ecosystems separate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;application release&lt;/li&gt;
&lt;li&gt;database migration&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Application
v2.0.0

Database
Migration 001
Migration 002
Migration 003
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nobody tries to squeeze both into one version number.&lt;/p&gt;

&lt;p&gt;Unfortunately, Odoo only gives us one.&lt;/p&gt;




&lt;h3&gt;
  
  
  Our Development Workflow
&lt;/h3&gt;

&lt;p&gt;Our company does &lt;strong&gt;not&lt;/strong&gt; have disposable development databases.&lt;/p&gt;

&lt;p&gt;Instead, we have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Developer
      │
      ▼
Shared Development Server
(real company users)
      │
      ▼
QA
      │
      ▼
Production
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The shared development server contains real data.&lt;/p&gt;

&lt;p&gt;Sales use it.&lt;/p&gt;

&lt;p&gt;QA uses it.&lt;/p&gt;

&lt;p&gt;Project members use it.&lt;/p&gt;

&lt;p&gt;Because of that, every deployment to this server becomes part of the database history.&lt;/p&gt;

&lt;p&gt;That immediately breaks many traditional versioning assumptions.&lt;/p&gt;




&lt;h3&gt;
  
  
  The Problem with Semantic Versioning
&lt;/h3&gt;

&lt;p&gt;Semantic Versioning asks questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is this a major change?&lt;/li&gt;
&lt;li&gt;Is this a minor feature?&lt;/li&gt;
&lt;li&gt;Is this a patch?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our team had a different question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"We deployed a new build to the shared development server. Which number do we bump?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Semantic Versioning doesn't answer that.&lt;/p&gt;

&lt;p&gt;Odoo documentation doesn't answer that.&lt;/p&gt;

&lt;p&gt;Different Odoo teams even interpret the five-part version differently.&lt;/p&gt;

&lt;p&gt;Eventually we realized something.&lt;/p&gt;

&lt;p&gt;We weren't trying to version software.&lt;/p&gt;

&lt;p&gt;We were trying to version our deployment lifecycle.&lt;/p&gt;




&lt;h2&gt;
  
  
  Introducing FckVer
&lt;/h2&gt;

&lt;h3&gt;
  
  
  FckVer (Fuckantic Versioning)
&lt;/h3&gt;

&lt;p&gt;Because sometimes software engineering deserves an appropriately named versioning system.&lt;/p&gt;

&lt;p&gt;The format is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;18.0.RELEASE.HOTFIX.DEV
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;where&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;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;18.0&lt;/td&gt;
&lt;td&gt;Odoo version&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RELEASE&lt;/td&gt;
&lt;td&gt;Production release generation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HOTFIX&lt;/td&gt;
&lt;td&gt;Production hotfix generation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DEV&lt;/td&gt;
&lt;td&gt;Shared development deployment generation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Unlike Semantic Versioning, none of these numbers describe API compatibility.&lt;/p&gt;

&lt;p&gt;They describe our deployment lifecycle.&lt;/p&gt;




&lt;h3&gt;
  
  
  The Rules
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Rule 1
&lt;/h4&gt;

&lt;p&gt;Every deployment to the shared development server increments DEV.&lt;/p&gt;

&lt;p&gt;It doesn't matter whether the change is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;migration&lt;/li&gt;
&lt;li&gt;new feature&lt;/li&gt;
&lt;li&gt;bug fix&lt;/li&gt;
&lt;li&gt;refactoring&lt;/li&gt;
&lt;li&gt;view changes&lt;/li&gt;
&lt;li&gt;security rules&lt;/li&gt;
&lt;li&gt;XML data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If users receive a new build on the shared development server...&lt;/p&gt;

&lt;p&gt;...DEV increments.&lt;/p&gt;

&lt;p&gt;We call this a &lt;strong&gt;fump&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Definition&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;fump&lt;/strong&gt; = fucking bump&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h4&gt;
  
  
  Rule 2
&lt;/h4&gt;

&lt;p&gt;Production releases increment RELEASE.&lt;/p&gt;

&lt;p&gt;Suppose production currently runs&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;18.0.4.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Development continues:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;18.0.4.0.1
18.0.4.0.2
18.0.4.0.3
...
18.0.4.0.696
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Eventually QA signs off.&lt;/p&gt;

&lt;p&gt;Now comes an important step.&lt;/p&gt;

&lt;p&gt;Before deploying to production, we perform a &lt;strong&gt;release fump&lt;/strong&gt; on the shared development server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;18.0.5.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No code changes.&lt;/p&gt;

&lt;p&gt;No migration changes.&lt;/p&gt;

&lt;p&gt;Nothing.&lt;/p&gt;

&lt;p&gt;Only the version changes.&lt;/p&gt;

&lt;p&gt;Then we perform one final smoke test.&lt;/p&gt;

&lt;p&gt;If everything passes...&lt;/p&gt;

&lt;p&gt;Deploy &lt;strong&gt;that exact build&lt;/strong&gt; to production.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Shared Dev
18.0.5.0.0

↓

Production
18.0.5.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Production always receives the exact version that was tested.&lt;/p&gt;




&lt;h4&gt;
  
  
  Rule 3
&lt;/h4&gt;

&lt;p&gt;Hotfixes increment HOTFIX.&lt;/p&gt;

&lt;p&gt;Suppose production is&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;18.0.5.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An emergency fix is required.&lt;/p&gt;

&lt;p&gt;The hotfix becomes&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;18.0.5.1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That version is tested.&lt;/p&gt;

&lt;p&gt;Then deployed.&lt;/p&gt;

&lt;p&gt;Development continues from there.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;18.0.5.1.1
18.0.5.1.2
18.0.5.1.3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Typical Lifecycle
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;18.0.4.0.0   Production Release 4

18.0.4.0.1   Dev deployment
18.0.4.0.2
18.0.4.0.3
...
18.0.4.0.696

18.0.5.0.0   Release fump
              Final smoke test

18.0.5.0.0   Production Release 5

18.0.5.0.1   New development
18.0.5.0.2

18.0.5.1.0   Production hotfix

18.0.5.1.1   Continue development
18.0.5.1.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Why This Works
&lt;/h3&gt;

&lt;p&gt;This approach gives us several nice properties.&lt;/p&gt;

&lt;h4&gt;
  
  
  Monotonic versions
&lt;/h4&gt;

&lt;p&gt;Odoo's version parser is always happy.&lt;/p&gt;

&lt;p&gt;Every version is greater than the previous one.&lt;/p&gt;




&lt;h4&gt;
  
  
  No version rewrites
&lt;/h4&gt;

&lt;p&gt;Once a version has been deployed anywhere shared, it is permanent.&lt;/p&gt;

&lt;p&gt;No rewriting history.&lt;/p&gt;

&lt;p&gt;No pretending intermediate versions never existed.&lt;/p&gt;




&lt;h4&gt;
  
  
  Production always runs a tested version
&lt;/h4&gt;

&lt;p&gt;There is never a last-minute version change immediately before production deployment.&lt;/p&gt;

&lt;p&gt;The production artifact is the same artifact that passed QA.&lt;/p&gt;




&lt;h4&gt;
  
  
  No Semantic Versioning debates
&lt;/h4&gt;

&lt;p&gt;Nobody asks&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Is this a patch?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Nobody asks&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Is this a minor feature?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Nobody asks&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Should this be 2.1 or 2.2?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The only question becomes&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Did we deploy a new build to the shared development environment?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If yes...&lt;/p&gt;

&lt;p&gt;Fump.&lt;/p&gt;




&lt;h3&gt;
  
  
  Is FckVer Better Than SemVer?
&lt;/h3&gt;

&lt;p&gt;No.&lt;/p&gt;

&lt;p&gt;It solves a different problem.&lt;/p&gt;

&lt;p&gt;Semantic Versioning describes compatibility.&lt;/p&gt;

&lt;p&gt;FckVer describes deployment history.&lt;/p&gt;

&lt;p&gt;For our Odoo workflow, deployment history is far more important than compatibility semantics.&lt;/p&gt;




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

&lt;p&gt;I don't claim this should become an industry standard.&lt;/p&gt;

&lt;p&gt;I don't even claim it's the best possible solution.&lt;/p&gt;

&lt;p&gt;But after trying to force Semantic Versioning into Odoo's module versioning, our team realized we were solving the wrong problem.&lt;/p&gt;

&lt;p&gt;Once we started treating the manifest version as a deployment lifecycle instead of a semantic version...&lt;/p&gt;

&lt;p&gt;Everything became much simpler.&lt;/p&gt;

&lt;p&gt;Sometimes the best engineering solution isn't the most elegant one.&lt;/p&gt;

&lt;p&gt;It's the one your team can understand at a glance.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;P.S.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes, the official name is &lt;strong&gt;Fuckantic Versioning&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You might want to abbreviate it to &lt;strong&gt;FckVer&lt;/strong&gt; because writing "fuck" into deployment scripts somehow felt unprofessional.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>odoo</category>
      <category>versioning</category>
      <category>engineering</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
