DEV Community

Cover image for Mind Discipline: Why Our AI Advisor Only Reads Hand-Crafted Contracts
Brett Ryan
Brett Ryan

Posted on Originally published at brettryan.dev

Mind Discipline: Why Our AI Advisor Only Reads Hand-Crafted Contracts

In my first post, I wrote about why I spent my first week writing zero business logic and instead built rig - our lightweight, POSIX-compliant local provisioning tool. It was my way of rejecting "wiki-ops" and applying Infrastructure-as-Code (IaC) discipline to our local environments so that a hardware failure means minutes of downtime, not a week.

But as I transitioned into Week Two, I was hit by a different kind of operational reality check.

For years, I had been building a comprehensive repository of system architecture, design decisions, and guidelines on Confluence. It was my digital home. So, knowing I would be creating a startup, I set to work writing my documentation in my spare time in preparation. But during a brief hiatus of inactivity, the space was silently, unceremoniously deleted. It was gone. Late nights of ideas, patterns, templates, and reference materials vanished into the cloud ether.

That loss was a violent reminder of a lesson I thought I'd fully mastered: if your documentation doesn't live alongside your code, you don't truly own it. Relying on third-party SaaS wikis to store the soul of your system architecture is just another form of "click-ops". It creates an artificial separation between the craftsmen writing the logic and the documentation that defines it.

But rather than mourning my lost Confluence space, I treated it as a catalyst. I decided that our young startup would not have a bloated, detached corporate wiki. Instead, we would treat Documentation as a Contract - a unified, git-backed human-and-machine contract that serves as the precise, zero-maintenance boundary for our AI systems.

Here is how losing my documentation led to a new architectural philosophy, and how we built a zero-overhead, "Anti-AI AI Strategy" that uses GitLab CI/CD and Google Workspace to run a secure, managed RAG pipeline.


The Anti-AI Strategy: Why We Refuse to Let AI Write Our Code

Walk into almost any tech startup today, and you’ll find developers blindly feeding raw codebases into LLMs, asking them to write entire features from scratch. The result is a flood of low-effort, AI-generated slop, code that looks functional on the surface but lacks architectural cohesion, contains silent regressions, and strips away the engineering "fingerprint" of the creator.

We refuse to work that way.

To scale with pride and precision, our engineering philosophy is built on a simple premise: human intent over AI generation. Great software is a work of hand-crafted art. The code is merely an implementation detail, a reflection of the craftsman's pride. It's so much fun when you hear a peer say "I just read your git-commit and it made me laugh".

We do not use AI as a quick syntax completion engine or a mindless pull-request generator. Instead, we treat AI as a Principal Architect and Advisor. It is our sparring partner for system design, edge case validation, and macro-architecture. But if the AI is to be an effective advisor, it needs clean, high-fidelity context. Feeding it a massive, messy codebase results in noisy context, token bloat, and tactical code generation instead of strategic guidance.

This is where the concept of Documentation-as-Contract comes in.

Before a single line of business logic is written, the engineer must define the boundaries of the component. They do this by drafting several markdown files directly within the project's repository:

  1. README.md: Describes the component’s internal mechanisms, local setup, and core intent. It explains the why and the how for human engineers.
  2. INTERFACE.md: Describes the public-facing boundaries. This includes the public-facing code interfaces (interfaces, abstract classes, records).
  3. API.md: Describes exposed ReST endpoints, gRPC/Protobuf contracts, GraphQL schemas.
  4. Any other content may be produced that may add or separate boundaries. For example, USAGE.md might make more sense in some cases than creating a massive README.md
  5. Infrastructure as Code may also live in infra/README.md as appropriate.

This documentation is the source of truth. If a public endpoint or module contract isn't documented in the API.md file or the interface contracts are not exposed in INTERFACE.md, then as far as the rest of the system (and our AI advisor) is concerned, it does not exist. By forcing ourselves to write the interface first, we ensure deep clarity of thought before code execution. I've said it so many times to peers - If you can't explain the contract clearly in text, the code behind it is probably too complex, or worse, it's not fully understood.


The Two-Tiered Context Architecture (Zero-Maintenance RAG)

You've probably seen the posts on Linkedin before, "How I used AI to create a RAG with 10 different pipeline components". It doesn't need to be so complex, and; you can do it with ease.

I originally subscribed to a Google Workspaces Business account just so I could get guaranteed private conversation history with Google Gemini, but then I started using Gemini Notebook (formerly NotebookLM). You can create a precise context window by adding just the sources you need when you interact. Either direct web sources, or; documents directly from Google Drive which auto-update as the document updates.

This prompted me the idea "Can I load my git-project documentation loaded to google workspaces as part of my CI/CD process?" This is where I took my concept of Documentation as a Contract and applied it directly to my AI strategy.

As part of this journey I set out a topology that centralises on a shared Google Workspace Drive called "Architecture". The primary consumer of this is my AI tools (Gemini Notebook), if it exists in the company, documentation must be stored here to back it. This is the knowledge repository, structured under automated folders mirroring the Gitlab project group path, and files named with the project embedded in them - this was a small lesson early on as it was hard to search, and differentiate sources when they all say README.md within Google Drive.

AI context is now surgically selected for each interaction by the author, they will select related components, either their API.md or INTERFACE.md depending on their interaction patterns, and may select relevant README.md for components that the AI needs a deeper understanding - maybe they are working on that component.

This approach allows Gemini to behave as both an architectural advisor and a project specialist for a given interaction. Since the author is selecting the precise components required - which are auto-updated, they get clear context with no overload and zero risk of the AI getting bogged down in needing to interpret low-level code.


Enter wabe-tools: Automating the Pipeline with Zero Overhead

With a separation of concerns in-place, without closing the automation loop, it would fail. This is why I created a small script to turn a Markdown file into a native gdoc file and have it uploaded to Google Drive. Combining this with a Gitlab component that can be included in any project to upload the documentation and we've completely closed the loop from architect to developer and back to our AI advisor network.

md2gdoc: The Google Cloud Document Loader

Firstly I needed a way to get content into google docs. They didn't have to be beautiful, but good enough for Gemini to get full context. I spent a day writing a python script with the following key requirements:

  • Must create a native Google Document file (gdoc)
  • Must create paths within Google Drive to the document
  • Must be able to specify a shared drive.

This is where the tool comes to the following contract.

md2gdoc [-h] [--title TITLE] [--drive DRIVE] [--folder FOLDER] file`
Enter fullscreen mode Exit fullscreen mode
Parameter         Description                      
file            Path to input Markdown/Text file 
--title TITLE   Title for the Google Doc         
--drive DRIVE   Drive name to upload to.         
--folder FOLDER Folder path within drive.        

It turns out that if you send a text file to Google Drive with the mimeType set to application/vnd.google-apps.document, the API automatically creates the google document and fills it with the text you pass, though; I am using gravitas-md2gdocs for basic formatting.

publish-docs: Gitlab Component to Close the Loop

Tying it all together is a Gitlab component that when included in a .gitlab-ci.yml pipeline will execute md2gdocs for each of the supplied documents. Sane defaults already look for the README.md file, but these may also be overridden.

Inputs

Inputs can be provided at the root and override-able at document item levels. Defaults are defined for our company documentation best practices that have been designed for our Gemini Notebook integration.

Input             Description                     
stage           Pipeline stage to run job in.
drive           Target Google Shared Drive name.
folder          Target folder path in Drive.    
docs            JSON string array of document objects.
docs.file       File to be sent to google drive.
docs.title      Google document title.
docs.full_title Allows providing a title that does not include the project name.
docs.drive      Item level drive override.      
docs.folder     Item level folder override.     

Usage

For a minimal implementation that publishes your project's README.md to our central Architecture as Components/$CI_PROJECT_PATH/$CI_PROJECT_NAME :: README, the following default configuration satisfies this requirement for most projects.

include:
  - component: $CI_SERVER_FQDN/my-group/wabe-tools/publish-docs@main
Enter fullscreen mode Exit fullscreen mode

infra-bootstrap-gcp: Granting Projects to Publish Documentation

From the get-go, I knew I wanted to be able to send documentation directly from my laptop for testing purposes, but more importantly, I wanted this to be executed directly from my CI/CD pipeline. This is where I came up with the infrastructure required to grant individual projects and/or Gitlab groups Attribute Based Access Control (ABAC) least privileged to Google's API's via OpenID Connect (OIDC).

Temporary friction gives the calluses to be stronger!

It's at this point where I felt friction with the Google Cloud API's and Identity and Access management (IAM) differences between Amazon Web Services (AWS) a point of friction, though; having been through it has given me broader understanding that will help me later.

Demonstrating the same Documentation-as-Contract standards here, the following is an extract of the inputs/outputs from the infra-bootstrap-gcp OpenTofu inputs/outputs section:

Inputs

Name Description
input_gitlab_group_ids List of groups that are granted access. Note: this is a direct ancestor to a project and ancestors of a direct group to a project are not supported.
input_gitlab_project_ids List of projects that are allowed access to write documents.
input_gitlab_root_project_path Path prefix for projects
input_gitlab_url GitLab URL used for the gitlab audience policy statement

Outputs

Name Description
google_organisation_id n/a
output_google_pool_provider_name Google Pool provider name used for the audience. GCP_WORKLOAD_IDENTITY_PROVIDER is to be populated with this value in the Gitlab CI/CD module which will create an audience that contains this value.
output_google_project_id n/a
output_google_project_number n/a
output_google_service_account_email Google Service account the Gitlab CI/CD module will use to impersonate requests. GCP_SERVICE_ACCOUNT_EMAIL is to be populated with this value.

The Documentation-as-Contract Pillars for AI and Humans

Combining principals of Documentation as Code, Contract-Driven Development and Context Window Engineering, we have established the 5 pillars that make up this framework:

  • Documentation is the Source of Truth: Code becomes a downstream implementation of a well-defined written design. If it isn't documented it doesn't exist.
  • Zero Context Overload: Surgically tailored context windows for our AI, maximising the quality of Gemini’s strategic advice.
  • CI/CD-Driven Architecture: We establish trust by providing the tools to ensure that documentation adjacent to code, is sent to our centralised documentation store only when code piplines succeed.
  • Prototyping Without Code: We can write, refine, and merge documentation first to validate an architectural idea or prototype before committing resources to build it.
  • Plumbing Code Auto-Documentation: For repetitive plumbing (like Terraform configurations), we use GitLab components like terraform-docs to auto-generate markdown files from code. This reverses the contract for the mundane, ensuring the plumbing documentation is always perfectly in sync.

RAD is a Discipline, Not a Luxury Suite

Many believe that Rapid Application Development (RAD) requires expensive enterprise software suites (Confluence, Jira, dedicated RAG search providers). Even I was fooled by my corporate discipline instilled in me over my career. With some forethought and discipline, you can build world-class developer experiences that are secure and scalable.

Today my company's tech stack consists of AWS as my primary cloud provider serving the content you're likely reading from AWS CloudFront, a Google Workspaces integration with Google Drive and Gemini+Notebook, Gitlab CI/CD to stitch it all together and strict disciplines with a focus on repeatability such as Infrastructure as Code (IaC) and company tooling. I completely own the IP with a low cost of ownership. The highest hitter being my Google Workspaces license which is still reasonable.


Where to From Here?

With my tooling in place, my deployment pipelines running, and our core strategy solidified, I am finally ready to start building the heart of the business.

As I begin writing our first services, my guiding architectural principle will be local-first, cloud-agnostic development. I want our applications to run flawlessly on a laptop with zero external dependencies, leveraging cloud-native features through clean facades and interfaces.

This is where the twin rails of the last two weeks come together:

  • rig will ensure that any developer tool, framework or cloud component needed for local-first development is instantly provisioned and standard across our environments with a single command.
  • publish-docs will ensure that as we design our components, boundary contracts (INTERFACE.md and API.md) are immediately pushed to our central Workspace, allowing Gemini to act as our strategic sounding board for the next engineering phase.

As central components, these will evolve over time, strengthening our base as we move forward.

In my next post, I will share the journey of developing to contracts allows one to continue to be productive even if not connected to the internet, by utilising a local first testing and development strategy and share my continued story of the Documentation-as-a-Contract for our AI advisor.

Top comments (0)