Managing an Open Source Project While Working Full-Time

“A lot of people think open source maintainers code all day.

Many of them actually finish a full-time job first.”

One thing I underestimated about open source was not the coding itself.

It was the consistency.

After a full 9–5 workday, sitting again in front of a screen to:

  • review pull requests
  • answer issues
  • write documentation
  • fix bugs
  • organize repositories

can become exhausting very quickly.

And the difficult part is that open source projects do not pause when you are tired.

There is always:

  • another issue to check
  • another feature idea
  • another bug report
  • another dependency update

A lot of people see active repositories and think maintainers are constantly productive.

In reality, many developers are managing these projects during:

  • evenings
  • weekends
  • lunch breaks
  • small free moments during the day

And honestly, balancing everything is difficult.

Sometimes you want to build features, but instead you spend the entire night:

  • cleaning labels
  • updating documentation
  • reviewing code
  • organizing issues

The bigger the project becomes, the more maintenance work appears around the code itself.

Consistency Matters More Than Intensity

Working 10 hours one weekend and then disappearing for a month usually hurts momentum more than making small improvements regularly.

Even:

  • one fixed bug
  • one answered issue
  • one cleaned README
  • one reviewed PR

still moves the project forward.

I think many developers avoid starting open source projects because they believe they need unlimited free time.

But most maintainers are probably just trying to make steady progress after work like everyone else.

I am currently in this situation myself — trying to balance:

  • a full-time job
  • an open source project
  • and personal life at the same time

And honestly, it can become overwhelming sometimes.

Final Thought

You do not need to work on your project every single day for 8 hours.

Small consistent progress over time is often what keeps open source projects alive long term.

Spring AI Explained — ChatClient, RAG, Advisors, and Every Core Component

Most Spring AI tutorials jump straight to code. You copy the dependency, paste the config, call ChatClient, and something works. But when you need to actually build something — a chatbot that remembers conversations, an API that answers questions from your own documents — you hit a wall. Because you don’t know what’s actually doing what. Friend’s Link

What Spring AI actually is — in one sentence

Spring AI is an abstraction layer that lets you wire LLMs into your Spring Boot app without hardcoding any particular AI provider.

That last part matters. OpenAI, Google Gemini, Anthropic Claude, and Ollama are running locally on your machine — Spring AI talks to all of them through the same API. Swap providers without touching your business logic. That’s the entire value proposition, and everything else is built on top of it.

Spring AI Components

ChatClient — the front door
ChatClient is the component you’ll interact with the most. It’s the fluent API that sits at the top of the stack and handles the actual request-response cycle with the LLM.

Think of it like a RestTemplate or a WebClient— but instead of calling a REST endpoint, you’re sending a prompt and getting a response back. It handles all the low-level connection details, request formatting, and response parsing so you don’t have to.

What makes ChatClient genuinely well-designed is its fluent builder style. You don’t configure it once globally and hope for the best. Each call is composable — you can set the system prompt, attach advisors, pass user input, and control the output format all in one readable chain.

It also separates two things that often get conflated: the default configuration you set at startup (your system prompt, default advisors, model parameters) and the per-request configuration you apply at call time. That separation matters in production, where different endpoints need different behaviours from the same underlying client.

PromptTemplate — how you talk to the LLM properly

A raw string shoved into an LLM is not a prompt. A prompt is a structured piece of text with placeholders, context, and instructions — and this PromptTemplate is how Spring AI handles that.

The idea is simple: you define a template with variables, and at runtime, you fill those variables in. Instead of building prompt strings with Java string concatenation — which gets messy fast — you define the shape of the prompt separately from the data that goes into it.

This matters for three reasons. First, it keeps prompts readable and maintainable. Second, it separates the “what to ask” from the “what data to inject” which is the same separation concerns you apply everywhere else in your codebase. Third, it makes prompt versioning possible. When your prompt needs tweaking, you’re editing a template, not hunting through business logic.

PromptTemplate also gives you a proper Prompt object that carries both the human message and the system message. That distinction — system prompt (the instructions) vs user prompt (the question) — is one of the most important things to understand when working with LLMs, and Spring AI models it explicitly.

EmbeddingModel — the piece that makes search smart

An EmbeddingModel takes text and converts it into a vector — a list of floating point numbers that represents the meaning of that text in multi-dimensional space.

That sounds abstract. Here’s the concrete thing to grasp: two pieces of text that mean similar things will produce vectors that are close to each other mathematically. “What’s your return policy?” and “How do I get a refund?” are different strings, but their vectors will be very close — because semantically, they’re the same question.

This is what makes semantic search possible. Traditional search matches keywords. Embedding-based search matches meaning. A user asking “how do I cancel my order” will find a document titled “Order cancellation policy” even if the words don’t overlap, because the meanings are geometrically close in vector space.

In Spring AI, EmbeddingModel is the interface that abstracts over whatever embedding service you’re using — OpenAI’s text-embedding-ada-002, Gemini’s embedding API, or a local model via Ollama. The abstraction is consistent regardless of provider, which means your RAG pipeline doesn’t break if you switch models.

VectorStore — where embeddings live

VectorStore is the database for embeddings. You put vectors in, and you query them by similarity — “give me the top 5 stored vectors that are closest to this query vector.”

It’s worth understanding that this is a fundamentally different kind of database from what you’re used to. You don’t query it with SQL. You don’t look things up by ID. You ask: which stored content is most semantically similar to this input? And it returns the matches ranked by similarity score.

Spring AI’s VectorStore interface abstracts over the actual storage engine underneath. In development, you might use SimpleVectorStore an in-memory implementation. In production, you’d swap to Pinecone, Weaviate, pgvector on top of Postgres, or Elasticsearch. The interface stays identical. Your code doesn’t change.

The VectorStore is also responsible for handling the metadata that travels alongside each vector — the document title, page number, source URL, whatever you stored at ingestion time. When it returns matching chunks, that metadata comes with it, so your prompt builder knows where the information came from.

Advisors — the middleware nobody talks about enough

This is the component most tutorials skip, and it’s arguably the most powerful part of the whole framework.

An Advisor in Spring AI is a piece of middleware that wraps around every ChatClient request. Before the request goes to the LLM, advisors can intercept it and modify it — add context, inject memory, apply safety rules, log the conversation, filter the input. After the response comes back, they can post-process it too.

The important thing to understand is that advisors form a chain. Each one wraps the next, like servlet filters in a web application. You configure which advisors run in which order, and each one has a defined responsibility.

QuestionAnswerAdvisor is the one you’ll use for RAG. Before your question reaches the LLM, this advisor takes that question, queries VectorStore for the most relevant chunks, and injects them into the prompt automatically. From ChatClient’s perspective, you just asked a question. Internally, your question has been enriched with your own data before the LLM ever sees it.

MessageChatMemoryAdvisor is what makes conversations persistent. Without it, every call to ChatClient starts fresh — no memory of what was said before. With it, previous turns from ChatMemory are injected into each new request so the LLM has context.

You can write your own advisors too. Any cross-cutting concern that applies to every LLM call — rate limiting, PII detection, response caching, A/B testing between prompts — belongs in an advisor, not in your business logic.

ChatMemory — giving the LLM a memory

LLMs are stateless. Every API call is completely independent. Ask an LLM “what’s the capital of France,” then ask “what did I just ask you,” and it has no idea — because, from its perspective, that second request is the first thing you’ve ever said.

ChatMemory is how Spring AI solves this. It’s a storage abstraction for conversation history. After each exchange, the message — both the user’s question and the LLM’s response — gets saved. On the next request, that history gets loaded and injected into the prompt so the LLM has context.

InMemoryChatMemory is the default — history lives in your application’s heap and disappears on restart. That’s fine for development and short stateless sessions. For production chatbots that need to remember users across sessions, you’d implement a persistent ChatMemory backed by Redis or a database.

There’s a real constraint here worth knowing upfront: every message you inject into the conversation history costs tokens. LLMs have a context window limit — usually somewhere between 8K and 128K tokens, depending on the model. If a conversation goes on long enough, the accumulated history will either exceed the limit and fail, or you’ll need to implement a summarisation strategy to compress older messages.

This is not a Spring AI problem — it’s a fundamental LLM constraint. But ChatMemory is where you manage it.

RAG Flow

How RAG brings it all together
RAG — Retrieval-Augmented Generation — is the pattern that makes Spring AI genuinely production-useful. The diagram above shows both phases. Here’s the thinking behind it.

The core problem: your LLM knows nothing about your company. It doesn’t know your product documentation, your internal policies, your customer data. Fine-tuning a model on your data is expensive, slow, and goes stale every time the data changes.

RAG is the pragmatic answer. Instead of teaching the model your data, you just hand it the relevant pages at the moment it needs them. Like giving a contractor a specific clause from the contract rather than asking them to memorise the whole thing.

The ingestion phase runs once, or whenever your data changes. Your documents are loaded, split into manageable chunks, embedded into vectors, and stored in a VectorStore. This is how your data gets indexed for semantic retrieval.

The query phase runs on every request. The user’s question is embedded into a vector. That vector is used to query the VectorStore for the closest matching chunks. Those chunks — plus the original question — get injected into the prompt. The LLM reads them as context and answers based on what it finds there.

The LLM never “learned” your data. It reads it fresh on each request, like an open-book exam. That framing matters because it sets the right expectations: if the relevant information isn’t in the retrieved chunks, the model will still try to answer — and that’s when hallucinations happen. RAG reduces hallucinations by providing grounding. It doesn’t eliminate them.

The part that controls retrieval quality isn’t the LLM and isn’t the vector database — it’s the chunking strategy. How you split your documents determines what gets retrieved. A chunk that’s too large buries the relevant detail in noise. A chunk too small loses the surrounding context that makes it meaningful. Getting chunking right is usually where the real tuning work happens.

The one-line mental model for each component

ChatClient — you talk to the LLM through this. PromptTemplate — You structure what you say. EmbeddingModel — converts meaning into math. VectorStore — stores and searches that math. Advisors — middleware that enriches every request automatically. ChatMemory — gives the conversation a past. Together, they’re the full stack for building LLM features that actually behave like software — predictable, configurable, and debuggable.

Effortless Dart Coding with dart_extensions_pro

AI Coding Agent MCP Architecture


Introduction
Introducing dart_extensions_pro a Dart package that offers a collection of handy extensions and helper functions designed to enhance the development process. By simplifying common tasks and providing streamlined solutions, it allows developers to write code more efficiently and focus on building features rather than repetitive tasks. Ideal for improving productivity, this package is a valuable tool for both novice and experienced programmers.

Key Features
📊 Comparison: Simplify comparison operations with intuitive extension methods.

📅** Date Handling:** Effortlessly manage date and time with a variety of helpful functions.

✍️ String Utilities: Enhance string manipulation with powerful utility functions.

📋 List Enhancements: Improve list handling with convenient extensions for common operations.

🧭 Navigation: Streamline navigation tasks with specialized navigation functions.

👆 Tap Gestures: Easily handle tap gestures to improve user interaction.

🔁 Iterable Enhancements: Optimize iterable processing with enhanced methods.

🎨 Color Conversion: Simplify color manipulations and conversions with dedicated functions.

🔢 Number Utilities: Access a range of number-related utilities for calculations and formatting.


🛠️ Utility Functions: Utilize various handy utility functions to simplify your coding experience.

Installation
Add dependency to your pubspec.yaml file & run Pub get

dependencies:
  dart_extensions_pro: ^0.0.1

And import package into your class file

import 'package:dart_extensions_pro/dart_extensions_pro.dart';
**Analytics**

Visit EXTENSIONS.md for a complete list of all the available extensions.

Extensions:                    271
Helper Classes:                7
Helper Functions & Getters:    21
Typedefs:                      7
Mixins:                        2

Here’s a quick preview of dart_extensions_pro,
String extension

'hello'.iscapitalize(); // Capitalizes first letter // Hello
'Copy this text'.copyTo(); // Copies string to clipboard
'[email protected]'.isValidEmail(); // Checks if valid email // true
'flutter'.reverse(); // Reverses string // rettulf
'madam'.isPalindrome(); // Checks for palindrome // true
'flutter example'.toCamelCase(); // Converts to camel case // FlutterExample
'{"name": "Flutter"}'.decodeJson(); // Parses JSON string to map // {name: Flutter}

Comparison extension


5.gt(3);  // true, checks if 5 is greater than 3
3.lt(5);  // true, checks if 3 is less than 5
5.eq(5);  // true, checks if 5 is equal to 5
3.lte(3); // true, checks if 3 is less than or equal to 3
5.gte(3); // true, checks if 5 is greater than or equal to 3
5.ne(3);  // true, checks if 5 is not equal to 3

Date extension

DateTime.now().isSameDate(DateTime(2023, 9, 14));  // true, checks if today matches the provided date
DateTime.now().isToday();  // true, checks if today is today
DateTime.now().isTomorrow();  // true, checks if today is tomorrow (unlikely)
DateTime.now().wasYesterday();  // true, checks if today is yesterday (false)
DateTime.now().addDays(5);  // adds 5 days to the current date
DateTime.now().addMonths(3);  // adds 3 months to the current date
DateTime.now().addYears(2);  // adds 2 years to the current date
DateTime.now().subtractDays(7);  // subtracts 7 days from the current date
DateTime.now().subtractMonths(1);  // subtracts 1 month from the current date
DateTime.now().subtractYears(1);  // subtracts 1 year from the current date

List extension

final list = [1, 2, 3] << 4;  // [1, 2, 3, 4], appends 4 to the list using the `<<` operator
list.replaceFirstWhere(10, (item) => item == 2);  // true, replaces the first occurrence of 2 with 10
list.replaceLastWhere(20, (item) => item > 1);  // true, replaces the last item greater than 1 with 20

Navigation extension

context.to(MyPage());  // Navigates to `MyPage` using `to()`
context.toNamed('/home');  // Navigates to the named route '/home' using `toNamed()`
context.back();  // Pops the current route using `back()`
context.backUntil((route) => route.isFirst);  // Pops routes until the first one using `backUntil()`
context.toWithReplace(AnotherPage());  // Replaces current route with `AnotherPage` using `toWithReplace()`
context.replaceWithNamed('/dashboard');  // Replaces the current route with named route '/dashboard' using `replaceWithNamed()`
context.toAndRemoveAll(HomePage(), (route) => false);  // Navigates to `HomePage` and removes all previous routes using `toAndRemoveAll()`
context.toNamedAndRemoveAll('/login', (route) => false);  // Navigates to named route '/login' and removes all previous routes using `toNamedAndRemoveAll()`

Gesture extension

widget.onInkTap(() => 'Tapped!'.logMsg());  // Adds an ink splash effect with `onInkTap()`
widget.onTap(() => 'Tapped!'.logMsg());  // Adds a basic tap gesture with `onTap()`
widget.onDoubleTap(() => 'Double Tapped!'.logMsg());  // Adds a double-tap gesture with `onDoubleTap()`
widget.onTapCancel(() => 'Tap Cancelled!'.logMsg());  // Adds a tap cancel gesture with `onTapCancel()`
widget.onLongPress(() => 'Long Pressed!'.logMsg());  // Adds a long press gesture with `onLongPress()`
widget.onTapDown((details) => 'Tap Down!'.logMsg());  // Adds a tap down gesture with `onTapDown()`
widget.onScale(
  onScaleStart: (details) => 'Scale Started!'.logMsg(),
  onScaleUpdate: (details) => 'Scaling!'.logMsg(),
  onScaleEnd: (details) => 'Scale Ended!'.logMsg(),
);  // Adds a scale gesture with `onScale()`

Iterable extension

iterable.lastElementIndex;  // Returns the index of the last element or -1 if empty.
iterable.hasSingleElement;  // Checks if the iterable has exactly one element.
iterable.addAllMatchingTo(targetList, (e) => e.isEven);  // Adds elements matching the predicate to the target list.
iterable.whereFilter((e) => e.isEven);  // Filters elements matching the predicate.
iterable.whereFilterIndexed((index, e) => index % 2 == 0);  // Filters elements with their index.
iterable.mapTransform((e) => e.toString());  // Transforms each element and maps to a new iterable.
iterable.skipElements(2);  // Skips the first 2 elements.
iterable.takeLastElements(2);  // Takes the last 2 elements.
iterable.skipWhileElements((e) => e < 5);  // Skips elements while the predicate is true.
iterable.skipLastElements(2);  // Skips the last 2 elements.

Color conversion

String.toColor();  // Converts a hex color string to a Color object, assuming full opacity.
HexColor.getColorFromHex(hexColor);  // Converts a hex color string to an integer color value, adding alpha if missing.
HexColor(hexColor);  // Creates a HexColor instance from a hex color string.

Number conversion


num.negative;  // Converts positive numbers to their negative counterparts.
num.isBetween(value1, value2, {inclusive = false});  // Checks if [this] is between [value1] and [value2], inclusive if [inclusive] is true.
num.roundToDecimals(decimalPlaces);  // Rounds the number to [decimalPlaces] decimal places.
double.asRadians;  // Converts degrees to radians.
double.asDegrees;  // Converts radians to degrees.
T.maxim(upperBound, {exclusive = false});  // Limits the value to [upperBound], exclusive if [exclusive] is true.
T.minm(lowerBound, {exclusive = false});  // Ensures the value is not less than [lowerBound], exclusive if [exclusive] is true.
T.clampAtMin(lowerBound);  // Ensures the value is not below [lowerBound].
T.clampAtMax(upperBound);  // Ensures the value does not exceed [upperBound].
num.orZero;  // Returns this value or 0 if null.
num.orOne;  // Returns this value or 1 if null.
num.or(value);  // Returns this value or [value] if null.

Utility conversion

double.isWhole;  // Checks if the value is a whole number.
double.roundToPrecision(nthPosition);  // Rounds the value to [precision] decimal places.
bool.isCloseTo(other, {precision = 1.0e-8});  // Checks if the value is close to [other] within [precision].
double.randomDouble({max});  // Generates a random double between 0.0 (inclusive) and 1.0 (exclusive).
int Duration.inYears;  // Returns the number of whole years spanned by this [Duration].
bool Duration.isInYears;  // Returns `true` if the [Duration] is equal to or longer than one year.
int Duration.absoluteSeconds;  // Returns the number of seconds remaining after accounting for whole minutes.
void Map<K, V>.operator <<(MapEntry<K, V> entry);  // Inserts a [MapEntry] into the map using the `<<` operator.
String Map<K, V>.toJson();  // Converts the map into a JSON string.

For more information, check out the below link


dart_extensions_pro | Flutter package

A Dart package that provides handy extensions and helper functions, designed to simplify and speed up development, making coding more efficient and streamlined.

favicon
pub.dev


Thanks for reading! If this post was helpful, feel free to share it and follow for more Flutter tips and tutorials. Keep coding and stay awesome!

Introducing Agent Note: saving the why behind AI-assisted code in Git

Agent Note — AI conversations saved to Git

Hi, I’m wasabeef.

I have been using coding agents such as Claude Code, Codex CLI, Cursor, and Gemini CLI regularly in daily development.

They no longer feel like experiments. They can already produce reviewable Pull Requests. But while reviewing AI-assisted changes, I kept running into the same problem.

A diff tells you what changed. It does not tell you why it changed.

That is already a problem with human-written commits when the commit message is weak. With AI-assisted commits, the missing context is even larger: the prompt, the response, the discussion that led to the implementation, the agent that touched each file, and the reason a particular path was chosen.

That is why I built Agent Note.

Agent Note — AI conversations saved to Git

This article focuses less on the exact usage and more on why this kind of record is needed, and how Agent Note keeps that context in Git.

What is missing in AI-era code review

AI coding agents have become common in everyday development.

They write code quickly. They add tests. They update documentation. They can even open Pull Requests.

But review exposes a different problem.

The final diff does not show the background of the implementation.

  • What request started the change?
  • What assumptions did the AI make?
  • Did the direction change halfway through?
  • Is this a generated bundle, or source code someone intentionally edited?
  • Which commits were mostly AI-assisted, and which were mostly human follow-up?

In human-to-human development, commit messages, Pull Request descriptions, and review comments have carried that context.

In AI-assisted development, prompts and responses also belong in the review context. Without them, reviewers lose the trail before review even starts.

Until now, the conversation with the AI often stayed inside the agent UI or a local transcript. Once the session ended, the team usually received only the commit and the Pull Request.

The reason behind the change disappears.

AI review tools need context too

I also use AI review tools such as Copilot, CodeRabbit, Devin, and Greptile.

Their main inputs are usually the diff and the repository code.

That means AI can review AI-written code without seeing the prompt or intent that produced it.

When that happens, the review tends to stay near the surface of the diff.

To judge whether an implementation matches the intended change, a reviewer needs more than the final code. The reviewer needs to know what the author asked for, what the agent understood, and which parts of the repository were supposed to change.

Agent Note keeps that context in the Pull Request in a form AI review tools can read.

It renders a human-readable summary in the Pull Request body, and also embeds an agentnote-reviewer-context hidden comment. It is invisible in the rendered PR body, but AI review tools that read the raw Pull Request description can use it to understand changed areas, review focus, and author intent.

The reviewer gets more than the diff.

Today

git diff
Pull Request description

Prompt?       missing
Response?     missing
Why this way? reviewers have to infer it

With Agent Note

git diff
Pull Request description
refs/notes/agentnote
Dashboard

Prompt / Response / Context / AI Ratio stay connected to the commit

What gets recorded

Agent Note saves the AI conversation and changed files for each commit.

Think of it as git log with the AI conversation behind the change attached to it.

It records four kinds of information.

Data What it helps you see
Prompt / Response What was requested and how the AI answered
Files Which files the agent touched
AI Ratio A practical estimate of how much of the commit involved AI
Context Extra context when the prompt alone is too short

For example, a prompt like yes, implement it does not carry enough meaning when it appears alone in a Pull Request.

Agent Note does not try to inflate that prompt. Instead, when the surrounding commit evidence helps, it can attach a short Context note.

Context shown in the Agent Note Dashboard

The point is not to say “this code is correct because AI wrote it” or “this code is risky because AI wrote it.”

The point is to give reviewers better evidence.

How it works

Agent Note is not a hosted service.

It adds a thin recording layer next to the normal Git workflow.

You prompt your coding agent
        │
        ▼
Agent hooks save the conversation and session info
        │
        ▼
The agent edits files
        │
        ▼
Hooks or local transcripts record changed files
        │
        ▼
You run `git commit`
        │
        ▼
A Git hook links the session to the commit
        │
        ▼
Agent Note writes a Git note for that commit
        │
        ▼
Agent Note's pre-push hook shares `refs/notes/agentnote`

Temporary session data lives under .git/agentnote/.

The permanent record lives in refs/notes/agentnote.

Agent Note does not modify the commit diff. It adds only a short session trailer to the commit message and stores the detailed record in Git notes. When you need the AI context behind a commit, you read the Git note.

Why Git notes

The design constraint I cared about most was avoiding unnecessary workflow changes.

I did not want to replace git commit, and I did not want the core record to depend on a hosted service.

The context behind AI-assisted code should be a team asset, just like the commit itself. Keeping that context in Git felt natural.

Git notes let Agent Note attach structured data to a commit without changing the regular commit history.

That balance felt right.

  • Use normal git log and Pull Requests most of the time
  • Read Agent Note data only when you need the deeper context
  • Share it with the team through refs/notes/agentnote
  • Avoid requiring a hosted service

The design keeps AI development context close to Git instead of sending it somewhere else.

What Agent Note does not do

Agent Note is not a tool for proving that AI-written code is correct.

AI Ratio is not an automatic judgment of responsibility or quality. It is a practical signal for understanding how much AI involvement a commit appears to have.

Agent Note also does not claim perfect line-to-prompt attribution today. agent-note why is a shortcut from a line, to the blamed commit, to the prompts, responses, and context attached to that commit.

The goal is not to replace review. The goal is to keep the context reviewers need from disappearing.

How it fits with Spec-Driven Development

Spec-Driven Development makes the intent explicit before implementation.

That works well with AI coding agents. If the input is vague, the agent may still produce code quickly, but reviewers later have to guess why the implementation took that shape.

A spec alone does not preserve the implementation conversation. It does not show how the agent interpreted the task, what changed during the session, or which prompts ended up in each commit.

If the spec is the intent before implementation, Agent Note is the execution record after implementation.

Together, they let reviewers compare the implementation against the spec, and also inspect the AI conversation that produced the commit.

How it relates to Entire

Agent Note is not the only project working on this problem.

Entire also connects the context behind AI-assisted code changes to Git. Entire records prompts, transcripts, tool calls, changed files, and other session data as Checkpoints linked to commits. It is a broader system for agent development history, including rewind, resume, search, and a web UI.

Agent Note is intentionally narrower.

It focuses on commits and Pull Request review. The persistent record lives in Git notes under refs/notes/agentnote, and the main surfaces are the PR Report, Dashboard, hidden reviewer context for AI review tools, and agent-note why.

I do not see this as a matter of which approach is correct. The scope is different.

If you want full session Checkpoints, rewind, resume, and repository-wide search, a system like Entire makes sense. If you mainly want lightweight commit-level review context in Pull Requests, Agent Note is designed for that narrower workflow.

PR Report and Dashboard

In Pull Requests, Agent Note renders a human-readable summary.

## 🧑💬🤖 Agent Note

**Total AI Ratio:** ██████░░ 73%
**Model:** `claude-sonnet-4-20250514`

| Commit | AI Ratio | Prompts | Files |
|---|---|---|---|
| ce941f7 feat: add auth | ████░ 73% | 2 | auth.ts, token.ts |

Open Dashboard ↗

The PR Report is the entry point for review.

The Dashboard is for deeper reading.

In the Dashboard, you can inspect Prompt / Response, changed files, AI Ratio, and diffs by PR and by commit.

Agent Note Dashboard preview

The report answers “what should I look at first?” The Dashboard answers “what happened in this commit?”

The idea behind agent-note why

Agent Note also includes agent-note why.

It starts from a target line, uses git blame to find the commit, then reads the Agent Note attached to that commit.

npx agent-note why README.md:111

It does not claim exact line-to-prompt attribution yet.

But even without a new schema, connecting an individual line to the commit conversation is useful. It shortens the path from “why is this line here?” to “what did we ask the agent to do in that commit?”

Eventually, I want to get closer to line-level explanations. The MVP is intentionally smaller: connect existing Git blame data with existing Git note data and make the available context easy to reach.

Different agents expose different context

Agent Note supports multiple coding agents, but each agent exposes a different level of detail.

That is because every agent exposes hooks and transcripts differently.

Claude Code provides the richest signal today. Codex CLI, Cursor, and Gemini CLI are also supported, but Agent Note records only the prompt, response, changed files, and AI Ratio evidence that each agent can expose reliably.

I also do not want to overstate the evidence.

If Agent Note cannot know something reliably, it does not pretend to know it. AI Ratio is an estimate, not proof.

The latest support matrix is available in Agent Support.

Things to keep in mind

Agent Note records conversations with AI for the team.

That record should be handled carefully.

  • Do not put secrets in prompts or responses
  • When Git notes are pushed, the team can read the saved conversation
  • AI Ratio is an estimate, not an automatic judgment of quality or responsibility
  • Different agents expose different levels of detail
  • Gemini CLI support is still Preview

Agent Note is closer to review context than to an audit verdict.

Closing

The more we use AI coding agents, the less a diff alone is enough for code review.

Human commits have commit messages and Pull Request discussions. AI-assisted commits should also preserve prompts, responses, context, and AI Ratio.

Agent Note is an open source, Git-native way to do that.

If you want AI-assisted code to remain understandable after the session is over, please give Agent Note a try.

Hermes Agent Remembers You

For the past two years, the AI industry has obsessed over model intelligence.
Bigger context windows.
Smarter benchmarks.
More parameters.
Faster inference.
But most AI assistants still suffer from the same fatal flaw:
They forget everything.
Every session starts from zero.
Every workflow requires re-explaining context.
Every “AI agent” often behaves like a temporary script wearing a chatbot costume.
Then Hermes Agent arrived.
Built by Nous Research, Hermes Agent is not trying to be another copilot or another flashy autonomous demo. It is attempting something much more ambitious:
An AI system that evolves through use.
And that changes the conversation entirely.
What Is Hermes Agent?
Hermes Agent is an open-source autonomous AI agent framework designed around one central idea:
Persistence.
Not just persistent memory.
Persistent skills.
Persistent workflows.
Persistent identity.
Unlike traditional chat-based assistants, Hermes runs as a long-lived system that can continuously operate across platforms, tools, terminals, APIs, and messaging apps.
The official tagline says it best:
“The agent that grows with you.”
That sounds like marketing copy at first.
Until you understand how Hermes actually works.
The Core Breakthrough: AI That Learns Operationally
Most AI systems today are stateless.
Even when they simulate memory, the “memory” is usually just:
conversation history,
vector retrieval,
or manually injected context.
Hermes goes further.
After solving tasks, Hermes creates reusable “skills” from successful execution traces. Those skills become searchable operational knowledge the agent can reuse later.
This is the real innovation.
Hermes does not merely answer.
It accumulates experience.
That distinction matters more than most people realize.
Why Hermes Agent Feels Different
The easiest way to understand Hermes is this:
Chatbots respond.
Copilots assist.
Hermes persists.
That persistence creates entirely new behavior patterns.
A normal AI assistant:
solves a task,
forgets it,
and starts over next time.
Hermes:
solves a task,
stores successful workflows,
refines them,
and reuses them later.
Over time, your agent slowly becomes specialized around:
your workflows,
your preferences,
your infrastructure,
and your recurring problems.
That is much closer to hiring a junior operator than opening a chatbot.
The Three-File Architecture That Makes Hermes Unique
One of the most fascinating design decisions inside Hermes is its identity system.
According to community documentation and framework breakdowns, Hermes organizes persistent behavior into three evolving files:
SOUL.md → personality, principles, behavioral constants
MEMORY.md → accumulated factual knowledge
USER.md → evolving understanding of the user
This is incredibly important conceptually.
Most AI systems merge everything into one giant context blob.
Hermes separates:
identity,
memory,
and user modeling.
That separation mirrors how humans actually operate.
You are not the same as your memories.
And your memories are not the same as your understanding of another person.
Hermes encodes that distinction directly into the architecture.
That is not just clever engineering.
It is a glimpse into where agent design is heading.
Hermes vs Traditional Agent Frameworks
The current AI agent ecosystem is crowded:
LangChain
AutoGen
OpenClaw
CrewAI
OpenAI Agents SDK
countless orchestration layers
Most frameworks optimize for:
tool calling,
chaining,
orchestration,
or multi-agent coordination.
Hermes optimizes for continuity.
That is a fundamentally different design philosophy.
Framework Type Main Focus
LangChain Orchestration
AutoGen Multi-agent collaboration
OpenAI Agents API-level workflows
OpenClaw Autonomous execution
Hermes Agent Persistent self-improving operation
Hermes is less interested in “agent demos.”
It is trying to become infrastructure.
The Most Underrated Feature: Multi-Platform Presence
Hermes can operate across:
Telegram,
Discord,
Slack,
WhatsApp,
Signal,
email,
terminal interfaces,
IDE integrations,
and more.
At first glance, this sounds like a convenience feature.
It is not.
This transforms Hermes from a tool into an ambient computing layer.
Imagine:
asking your agent something from Telegram,
continuing the task in VS Code,
receiving summaries through Slack,
and letting background automations continue overnight.
The agent persists independently from the interface.
That architecture feels much closer to operating systems than applications.
Local-First AI Finally Becomes Real
One reason Hermes exploded in popularity is because it aligns perfectly with a growing movement in AI:
AI sovereignty.
Developers increasingly want:
local models,
self-hosted infrastructure,
private memory,
ownership of workflows,
and freedom from API lock-in.
Hermes supports multiple providers and local inference backends, including OpenAI-compatible APIs, Hugging Face integrations, Anthropic, Google, OpenRouter, and local stacks like LM Studio.
It can run:
on a laptop,
on a cheap VPS,
or on GPU infrastructure.
That flexibility matters.
For years, powerful AI systems required centralized cloud dependency.
Hermes suggests another future:
personal AI infrastructure.
The Real Shift: From Prompt Engineering to Agent Evolution
Prompt engineering dominated the first wave of generative AI.
But Hermes points toward something bigger:
Experience engineering.
The value is no longer just crafting prompts.
The value becomes:
shaping long-term agent behavior,
building reusable operational knowledge,
and evolving persistent systems over time.
This is a massive conceptual shift.
Instead of:
“How do I prompt the model?”
The question becomes:
“How do I train my operational agent ecosystem through use?”
That is a much more interesting future.
The Biggest Weaknesses of Hermes Agent
Hermes is exciting.
But it is not magic.
There are still major limitations.

  1. Complexity
    Hermes is not beginner-friendly.
    Running persistent self-hosted agents requires:
    infrastructure knowledge,
    API management,
    model selection,
    memory management,
    and operational discipline.
    This is still very much a builder’s tool.
  2. Long-Running Drift
    Persistent agents introduce a new category of problems:
    memory pollution,
    behavioral drift,
    recursive errors,
    and degraded context quality over time.
    An agent that remembers incorrectly can become dangerous faster than one that forgets.
  3. Autonomous Reliability Is Still Hard
    Even advanced agents still struggle with:
    long task chains,
    edge cases,
    hallucinated tool use,
    and execution reliability.
    Hermes improves the structure around the model.
    It does not magically solve reasoning limitations.
    Why Developers Are Paying Attention
    Hermes Agent grew extraordinarily fast because it landed at the exact right moment.
    The industry is moving from:
    isolated prompts
    toward:
    persistent autonomous systems.
    From:
    AI chat
    toward:
    AI operations.
    From:
    asking questions
    toward:
    delegating workflows.
    Hermes is one of the clearest early examples of what that transition looks like in practice.
    My Take: Hermes Agent Is More Important Than Most People Realize
    The biggest idea behind Hermes is not tool use.
    It is not automation.
    It is not memory.
    The biggest idea is this:
    AI systems are starting to accumulate operational experience.
    That changes everything.
    Because once agents can:
    remember,
    refine,
    specialize,
    and evolve through execution,
    they stop behaving like software in the traditional sense.
    They begin behaving more like digital coworkers.
    We are still early.
    The systems are imperfect.
    The reliability problems are real.
    But Hermes Agent feels like one of the first open-source projects pointing clearly toward the next era of AI:
    Not isolated intelligence.
    Persistent intelligence.

Building a UI for a Team Task Manager (Laravel + Tailwind)

Welcome page

“I’ve been working on a project, a simple team task management system built with Laravel. After finishing the backend features like teams, invitations, and authentication, I finally shifted my focus to something I was avoiding for quite a while now: the UI. I also added a name for this project instead of just calling it a team task manager. The website name is Worklio.

Here’s the home page of the website:
Welcome page

I’m keeping the UI as simple as possible because my main focus is learning the backend side. I also use ChatGPT to help generate some of the frontend code, and the results have been surprisingly good. Right now, I just need to break parts of the UI into reusable components to make the codebase easier to read and maintain, while also centralizing repeated logic and code.

Here’s the rest of the pages:

Team Page

Team page

Show Single Team Page with Projects

Project Page

What’s next

I currently have both frontend and backend for teams, invitations, projects, and now I’ll be working on the task part.

Note: I’m using ChatGPT as part of my learning process—to sanity-check ideas, understand Laravel patterns, and think through tradeoffs. I still write the code myself and use the project to test whether I actually understand what I’m building.

GeekNews AI Weekly Deep Dive – 2026-05-18

AI weekly deep dive cover

이번 주 AI 이슈는 새 모델 과시보다 실제 운영 단위에서 AI를 어떻게 끼워 넣고 통제할지에 더 무게가 실렸습니다. 제품 경험에 자연스럽게 녹이는 통합 전략, 실제 하드웨어·예산에 맞는 선택, 그리고 프로세스 병목을 정확히 짚는 운영 감각이 공통 화두로 떠올랐습니다.

1. AI는 기술이지, 제품이 아니다

핵심 내용 요약: 이 글은 AI를 독립적인 ‘킬러 제품’으로 보기보다, 무선 네트워킹처럼 모든 제품에 스며드는 기반 기술로 봐야 한다고 주장합니다. 저자는 AI가 아이폰 사용 경험을 바꾸는 것은 맞지만, 2030년에도 호출·소통·확인 같은 핵심 상호작용의 중심 기기는 여전히 스마트폰일 가능성이 높다고 봅니다. 결론적으로 애플의 경쟁력은 AI 자체를 전면에 내세우는 것이 아니라, 사용자가 기술을 의식하지 않게 제품 경험으로 통합하는 데 있다는 관점입니다.

2. whichllm – 내 하드웨어에서 실제로 돌아가고 최고 성능을 내는 로컬 LLM 찾기

핵심 내용 요약: whichllm은 하드웨어에서 ‘돌아가기만 하는’ 모델이 아니라, 실제 벤치마크와 최신성·신뢰도 보정을 반영해 가장 성능이 좋은 로컬 LLM을 고르는 CLI 도구입니다. GPU·CPU·RAM 자동 감지 후 모델을 랭킹하고, 근거 수준 태깅과 계보 기반 감점으로 오래되거나 과장된 점수의 영향력을 줄여 추천 정확도를 높입니다. 또한 run·plan·upgrade 같은 명령으로 즉시 실행, 구매 전 시뮬레이션, 업그레이드 비교까지 한 흐름에서 지원해 실사용 의사결정을 단순화합니다.

3. AI 구독은 엔터프라이즈의 시한폭탄

핵심 내용 요약: 이 글은 주요 AI 기업들이 낮은 구독 가격으로 기업 도입을 빠르게 늘렸지만, 실제 토큰 비용과의 격차가 커 향후 가격 인상·사용량 제한·종량제 전환이 불가피하다고 주장합니다. 특히 에이전트형 사용이 늘면서 좌석당 계산 자원이 급증해, 현재는 작아 보이는 비용이 기업 예산에서 별도 관리가 필요한 수준으로 바뀔 수 있다고 경고합니다. 따라서 기업은 좌석 수가 아니라 실제 사용량을 기준으로 비용을 추적하고, 가격 충격에 대비한 시나리오와 벤더 대안을 미리 준비해야 한다고 제안합니다.

4. AI가 여러분의 프로세스를 더 빠르게 만들지는 않을 것 같습니다

핵심 내용 요약: 이 글은 소프트웨어 개발 속도의 핵심 병목이 코딩 자체가 아니라 모호한 요구사항을 실행 가능한 문제로 정제하는 상류 과정에 있다고 설명합니다. AI가 코드 생성을 빠르게 해도 도메인 지식과 상세한 맥락이 부족하면 결과 품질이 떨어지므로, 실제로는 더 정교한 입력과 지속적인 사람의 개입이 필요하다는 점을 강조합니다. 결국 프로세스 개선의 우선순위는 병목 단계에 고품질·예측 가능한 입력을 공급하는 구조를 만드는 것이며, AI는 그 기반 위에서만 의미 있게 속도를 높일 수 있다고 결론짓습니다.

5. dev3000 – AI 디버깅을 위한 웹 앱 개발 타임라인 통합 캡처 도구

핵심 내용 요약: dev3000은 개발 서버 실행 중 발생하는 서버 로그, 브라우저 콘솔, 네트워크 요청, 사용자 상호작용, 자동 스크린샷을 시간순으로 통합 기록해 AI가 문제 맥락을 한 번에 이해하도록 돕는 디버깅 도구입니다. 수집된 기록은 프로젝트별 로그와 스크린샷으로 저장되며, 통합 에러 조회·심층 분석·URL 크롤링 같은 진단 명령을 통해 원인 파악과 수정 과정을 빠르게 반복할 수 있도록 설계되었습니다. 또한 다양한 웹 프레임워크와 Chromium 계열 브라우저, 헤드리스 실행, 에이전트 분할 화면 연동을 지원해 로컬 개발부터 CI 환경까지 동일한 흐름으로 활용할 수 있습니다.

6. AI와 함께 일하며 복리처럼 쌓아 성장하는 법

핵심 내용 요약: 이 글은 AI 협업 성과를 누적시키는 핵심 원칙으로 컨텍스트를 체계적으로 정리하고, 선호와 작업 규칙을 설정 파일에 명시하며, 저비용 검증 루프를 앞단에 배치하고, 더 큰 단위의 일을 위임한 뒤 피드백을 다시 시스템에 반영하는 과정을 제시합니다. 특히 프로젝트 문서와 메모리 계층을 구조화해 세션마다 빠르게 온보딩하고, 스킬과 가이드를 지연 로딩 방식으로 운영해 컨텍스트 비용을 줄이면서도 재현 가능한 워크플로를 만드는 점을 강조합니다. 나아가 병렬 세션 운영과 드리프트 점검, 트랜스크립트 기반 규칙 개선을 통해 개인 생산성을 팀 단위 협업 품질로 확장할 수 있다고 설명합니다.

7. Google의 생성형 AI 검색 기능 최적화 공식 가이드

핵심 내용 요약: Google은 AI Overviews·AI Mode 같은 생성형 검색 기능도 기존 검색 랭킹·품질 시스템 위에서 동작하므로, 기술적 SEO 기본기와 사람 중심의 고유한 콘텐츠 전략이 여전히 핵심이라고 명확히 안내했습니다. 특히 LLMS.txt, 인위적 청킹, AI 전용 문체 재작성, 부자연스러운 멘션 확보 같은 이른바 AEO/GEO ‘핵’은 효과가 없거나 비권장하며, 대신 크롤링 가능 구조·중복 최소화·이미지/영상 품질·사용자 만족도를 우선하라고 강조했습니다. 또한 브라우저 에이전트 등 에이전틱 경험 확산에 대비해 사이트 접근성과 구조적 명확성을 갖추는 것이 중장기 가시성에 유리하다고 정리했습니다.

이번 주 실행 제안

실무적으로는 더 강한 모델을 붙이는 것보다 비용 구조, 하드웨어 적합성, 입력 품질, 운영 제어 지점을 함께 설계하는 팀이 유리해 보입니다. 특히 AI를 별도 마법 상자로 다루기보다 기존 제품과 워크플로에 어떻게 스며들게 할지까지 포함해 판단해야 시행착오를 줄일 수 있습니다.

GeekNews Frontend Weekly Deep Dive – 2026-05-18

Frontend weekly deep dive cover

이번 주 프론트엔드 흐름은 웹 개발 도구가 더 정교한 실행 맥락과 작업 기록을 다루는 방향으로 진화하는 한편, 검색 노출과 텍스트 UI처럼 오래된 문제도 생성형 AI 시대 기준으로 다시 재설계되고 있음을 보여줬습니다. 특히 디버깅, 문서 탐색, 업무 기록, 에이전트 실행 환경이 한층 더 운영 친화적인 형태로 묶이는 흐름이 두드러졌습니다.

1. dev3000 – AI 디버깅을 위한 웹 앱 개발 타임라인 통합 캡처 도구

핵심 내용 요약: dev3000은 개발 서버 실행 중의 서버 로그, 브라우저 콘솔, 네트워크 요청, 자동 스크린샷, 사용자 인터랙션을 시간순으로 함께 수집해 AI가 문제 맥락을 한 번에 파악하도록 돕는 디버깅 도구입니다. Chrome DevTools Protocol 기반 모니터링 결과를 프로젝트별 로그와 스크린샷으로 저장하고, 에러 조회·심층 분석·크롤링 같은 명령으로 원인 추적을 빠르게 수행할 수 있게 설계되었습니다. 프레임워크 종류와 무관하게 적용 가능하며 에이전트 연동, 헤드리스 실행, 프로젝트별 브라우저 프로필 유지까지 지원해 실전 개발 흐름에 바로 붙일 수 있습니다.

2. Google의 생성형 AI 검색 기능 최적화 공식 가이드

핵심 내용 요약: Google은 AI Overviews와 AI Mode 같은 생성형 검색에서도 기존 SEO 원칙이 그대로 유효하다고 밝히며, 단기적인 ‘AEO/GEO 핵’보다 사용자에게 실제로 유용한 독창적 콘텐츠를 우선하라고 권고합니다. 특히 인덱싱 가능성과 크롤링 접근성, 명확한 페이지 구조, 중복 최소화 같은 기술 기반을 갖추고, 검색 변형별 억지 페이지 양산이나 AI 전용 재작성 같은 조작적 전략은 피해야 한다고 강조합니다. 또한 로컬·이커머스 정보 정비와 에이전트 친화적 웹 준비를 병행하되, 핵심은 사람 중심의 신뢰 가능한 비범용 콘텐츠를 꾸준히 제공하는 것이라고 정리합니다.

3. 끝까지 네이티브로, 텍스트가 필요해지기 전까지

핵심 내용 요약: 작성자는 SwiftUI·AppKit·TextKit을 오가며 Markdown 채팅 UI를 구현했지만, 전체 선택과 스트리밍 안정성 같은 기본 요구를 만족시키는 과정에서 성능 저하와 복잡성이 반복된다고 지적합니다. 반면 WebKit과 Electron에서는 텍스트 선택, 렌더링 품질, 타이포그래피, 통합 동작이 비교적 자연스럽게 확보되어 장문 대화형 UI에서 웹 기반 접근이 실용적이라는 결론에 이릅니다. 결국 문제의 핵심은 네이티브 기술의 우열보다도, 현대 텍스트 인터페이스를 제품 수준으로 빠르게 완성할 수 있는 구현 경로가 어디에 더 성숙해 있는가에 있다는 주장입니다.

4. Show GN: glowed – Ghostty용 터미널 Markdown 브라우저/에디터

핵심 내용 요약: glowed는 실행한 디렉터리를 기준으로 Markdown 파일을 스캔해 검색·미리보기·원문 편집을 한 흐름 안에서 처리하고, 선택한 문맥을 외부 LLM CLI 세션으로 넘길 수 있게 설계된 Ghostty 중심 TUI 도구입니다. 작성자는 보안 자격 증명을 앱이 직접 다루지 않고 기존에 로그인된 CLI를 호출하는 방식과, 백업을 포함한 원자적 저장 등 실사용 안정 장치를 초기 버전에 반영했다고 설명합니다. 다만 현재는 macOS+Ghostty 환경 최적화와 제한적인 호환성 검증을 전제로 하며, 사용자별 포크와 Homebrew tap 배포를 권장하는 분산형 운영 모델을 채택하고 있습니다.

5. Show GN: 셜록 – 당신이 오늘 뭘 했는지를 다 알고 있는 AI 노트 앱

핵심 내용 요약: 셜록은 회의 기록에 한정된 기존 노트 도구와 달리, 사용자의 화면에서 실제 업무 맥락을 읽어 일과를 자동으로 정리해 주는 Mac용 AI 노트 앱입니다. 별도 앱 연동 없이 브라우징·메신저·문서 작업 흐름을 기반으로 요약과 후속 할 일을 만들어 주며, 필요한 경우 하루 업무를 질문형 챗으로 다시 꺼내볼 수 있게 설계됐습니다. 데이터는 로컬 저장을 기본으로 하고 캡처 중지·기록 삭제 같은 제어권을 사용자에게 두어 프라이버시 우려를 줄이려는 방향이 분명합니다.

6. Zerostack – 순수 Rust로 작성된 Unix에서 영감을 받은 코딩 에이전트

핵심 내용 요약: Zerostack은 Rust로 만든 초경량 코딩 에이전트로, 낮은 메모리 사용량과 빠른 반응성을 강점으로 내세우며 다양한 LLM 제공자와 도구 실행 흐름을 지원합니다. 파일 편집·검색·셸 실행 같은 핵심 기능에 권한 모드와 승인 체계를 붙여 자동화 편의성과 안전성 사이를 조절할 수 있고, 세션 재개·프롬프트 전환·반복 루프·워크트리 연계 등 장기 개발 작업을 위한 운영 기능도 폭넓게 갖췄습니다. 커뮤니티 반응은 특히 저사양 환경에서의 실사용성과 확장 가능성에 주목하면서도, 일부 제공자 호환성과 기능 성숙도는 추가 개선이 필요하다는 평가를 함께 보여줍니다.

7. Google 검색의 생성형 AI 기능을 위한 웹사이트 최적화

핵심 내용 요약: 구글은 AI Overviews·AI Mode 같은 생성형 검색에서도 별도의 비법보다 기존 SEO 원칙이 여전히 핵심이라고 명확히 밝히며, AI 응답 역시 검색 인덱스 기반의 RAG와 쿼리 팬아웃으로 신뢰 가능한 페이지를 찾아 구성된다고 설명합니다. 따라서 흔한 정보 재가공보다 고유한 관점과 실제 경험이 담긴 비범용 콘텐츠, 그리고 크롤링·인덱싱·접근성·페이지 경험 같은 기술적 기반을 꾸준히 갖추는 것이 장기적인 노출 성과를 좌우한다고 강조합니다. 반대로 llms.txt 신설, 기계적 청킹, 과도한 롱테일 삽입, 인위적 언급 늘리기 같은 ‘AEO/GEO 해킹’은 불필요하거나 스팸 정책 위험이 있어 피해야 한다고 정리합니다.

이번 주 실행 제안

실행 관점에서는 새 도구의 데모보다 팀 워크플로에 안전하게 붙는지, 원문 품질과 맥락 보존을 실제로 개선하는지를 먼저 검증하는 편이 좋습니다. 특히 검색 최적화나 에이전트 도구 도입은 눈에 띄는 편법보다 구조적 접근성, 기록성, 검수 가능성을 확보하는 쪽이 오래 남습니다.

I tested my AI product tester on 3 real SaaS products. Every persona said no.

Two months ago I was about to ship a crypto signal product. It “worked technically” but I had zero
signal on whether anyone would subscribe.

So I wrote 12 fictional user personas as markdown files — a burnt veteran trader, a hostile compliance
officer, a YC partner, a noise-allergic fund manager — and built a Python harness that fed each one my
actual product transcripts and asked: “what would you actually do?”

The answers were brutally helpful. They killed features I’d spent weeks on. I open-sourced the harness
as personalab (MIT).

## Then I pointed it at 3 real products

1. personalab itself — yes, I tested my own tool with my own tool. 0/8 simulated B2B SaaS buyers
said they’d pay $99/mo. The case study became my own roadmap.

2. PostHog — 6/12 personas said “yes I’d pay” after reading a 7-day product transcript. Same 12 over
5-day agentic simulation: 0/12 sustained. The “yes” was first-impression optimism; the “no” was
multi-day reality.

3. Cal.com — 8/12 yes at $5-20/mo. And here’s the gold: 75% of complaints converged on ONE thing —
the free-plan “Powered by Cal.com” branding makes recipients suspect spam. 8 distinct personas
independently nailed the same conversion lever.

## A pattern emerges

After 3 case studies, the number of dominant friction clusters in a personalab run seems to correlate
with PMF stage:

  • Pre-PMF: 4-5 diffuse complaints (my own tool)
  • Mid-funnel: 5 distinct friction clusters (PostHog: price / learning / UI / compliance / privacy)
  • Late-funnel: 1-2 clean conversion levers (Cal.com: branding)

If this holds in case study #4+, personalab becomes a free PMF-stage diagnostic from a $1 LLM run.

## Honest disclaimer

The default personas accidentally encoded personalab-specific preferences, so some quotes leak when
reused on other products. I kept the bug in the case study writeup rather than rerunning with clean data
— it surfaces persona design as a real engineering concern.

## Try it


bash
  git clone https://github.com/g16253470-beep/personalab
  cd personalab && pip install -e .
  personalab run --mode static --personas ./personas --adapter your_adapter --llm gemini:gemini-2.5-flash

  40-line adapter, 12 default personas, MIT licensed.

  Repo: https://github.com/g16253470-beep/personalab

  Two questions for DEV

  1. What product would you point this at first?
  2. Real PMF business or just an OSS curiosity?

  Tell me where this falls apart — that's the next case study.

AI proposed 5 components for my parallel system. After walking one scenario, only 3 were real.

TL;DR — AI loves to design “enterprise-grade” systems for you: message queue, distributed lock, state machine service, scheduler, monitoring bus. Half of them aren’t real. The cheapest filter I know: before letting AI design anything, walk one concrete scenario through the system. Whatever shows up in the scenario is real. Whatever doesn’t — delete. This week it took me from a 5-component design down to 3 — and surfaced one critical component AI had missed entirely.

What I was building

This week I was extending aming-claw (an open-source AI code governance tool I’m building) to support parallel multi-agent development: multiple AI agents working on the same project simultaneously, each on its own branch, all of it merging back into trunk.

I asked AI to help me design it.

It came back fast. Confident. Five components:

- Message queue        (so tasks can line up)
- Distributed lock     (so agents don't step on each other)
- State machine service (so we track progress)
- Task scheduler       (so we know what runs when)
- Monitoring bus       (so we see what's happening)

Each component had a paragraph of justification. The diagram looked impressive. The names sounded right.

I almost just said “ok, build it.”

Why I didn’t

A thing I’ve learned working with AI on architecture: AI doesn’t filter for necessity. It filters for plausibility. The components it lists are real things real systems have — they’re just not necessarily things your system needs.

So instead of letting it design the system, I did one thing:

I walked a concrete scenario through the system before agreeing to anything.

Here’s an honest framing: nobody can look at a 5-component design and immediately tell you which 2 are load-bearing. AI can’t. Most engineers reading this can’t, not on inspection.

The good news:

You don’t need to know what to design. You just need to walk one scenario.

The scenario does the filtering for you.

Scenario 1: five tasks with dependencies

I started with the most boring scenario I could think of:

Five AI agents working in parallel. Each one on its own branch. The tasks have a dependency chain: 1 → 2 → 3 → 4 → 5. Task 2 needs what task 1 built. Task 5 needs everything before it.

I walked through what the system has to do:

  • Five tasks running in parallel — they need to queue for merging. OK, “message queue” was real.
  • BUT — they have to merge in dependency order. Not first-come-first-served. So a plain FIFO message queue isn’t enough. It has to be an ordered queue.

Already, one component refined. “Message queue” → “ordered merge queue.”

Nothing has been deleted yet. Keep going.

Scenario 2: the machine reboots mid-batch

Now the machine reboots. When it comes back up: task 1 already merged. Task 2 tried to merge and failed. Task 3 hadn’t started yet. Task 4 was waiting in queue. Task 5 was halfway through executing when the power cut.

I walked it again:

  • For the system to even know what state each task is in after a reboot, task state has to be on disk, not just in memory. Not a “state machine service” with its own server — just durable per-task state. (task_id → status → checkpoint.) That’s a column in a database, not a service.
  • Task 2 failed, but tasks 3-5 are downstream of it. The system has to recognize “upstream failed, downstream blocked” automatically. That’s not a separate component — it’s a query against the durable state.
  • Task 5 was mid-execution when the power cut. When the machine restarts, what stops a second copy from picking it up and racing the half-finished one? Each execution attempt needs a unique token — whoever has the newest token is the live runner, everyone else gets fenced off.

Now two more things have surfaced:

  • Durable per-task state (which AI called “state machine service” — but it’s not a service, it’s a table)
  • Fence tokens to prevent zombie reruns

And here’s the first thing that got deleted: distributed lock.

A distributed lock is “this resource is held by exactly one agent right now.” Fence tokens solve the same problem in a much weaker, much cheaper way: “the latest token wins, all stale tokens are ignored.” For agent merge work, that’s sufficient. Distributed locks would be massive overkill for the actual scenario.

1 component deleted, 0 lines of code written.

Scenario 3: the ordering itself was wrong

This one wasn’t in my original head-list. It only surfaced when I kept walking:

Five tasks ran. Three merged. Then it turns out the dependency order I gave the system was wrong — it should have been 1 → 3 → 2 → 4 → 5, not 1 → 2 → 3 → 4 → 5. The three already-merged tasks need to be rolled back as a batch and replayed in the correct order.

This is a scenario most systems never plan for. Per-task rollback is common — undo one merge. Batch rollback with replay is rarer.

  • Plain per-task revert doesn’t work — you can’t revert task 2 while leaving task 3 (which depends on task 2’s wrong order) intact.
  • The whole batch has to roll back atomically.
  • Then the system has to replay them in the new order, with all the graph artifacts (snapshots, indices, semantic projection, test results) re-derived per merge.

This is the component AI had not mentioned at all. It only surfaced because I walked a scenario nobody told me to walk.

Call it BatchMergeRuntime. It’s the rarest kind of architectural decision: not “should we have it” but “do we even know we need it?” — and the answer, for most teams, is not until production.

What the architecture actually became

After walking three scenarios:

Scenario What it surfaced
5 tasks with dependencies Ordered merge queue
Machine reboots mid-batch Durable task state + fence tokens
Dependency order was wrong Batch rollback + replay runtime
All of the above untested Test scenario matrix as P0.0 (highest priority)

Three real components. The fourth — the test scenario matrix itself — is a meta-component: the dry-run scenarios I just walked became the first acceptance bar for every subsequent PR. Anything that ships has to survive these scenarios before merge.

AI’s first design vs what scenarios required

AI’s first list Reality after scenario walk
Message queue ✅ Needed — but ordered, not FIFO
Distributed lock ❌ Deleted — fence tokens are sufficient
State machine service ✅ Needed — but as a table, not a service
Task scheduler ❌ Deleted — the ordered queue is the scheduler
Monitoring bus ❌ Deleted — each component emits its own events
(AI did not propose) ✅ Batch rollback runtime — surfaced only by scenario 3

Net: 5 → 3 components, plus the one critical piece AI had missed entirely.

The win is not “I deleted 2 components.” The win is I now know why each remaining component exists, which means I can explain it, scope it, and reject scope creep on it. That’s the difference between a system you built and a system you understand.

The method, in 3 steps

❌ Don't:   "Hey AI, design me a system that does X."
           → AI returns a plausible-looking inventory of components.
           → Half of them aren't real for your specific case.

✅ Do:      Step 1.  Write one concrete scenario yourself.
                    (Or: have AI write the scenario, you evaluate it.
                     Real numbers, real steps, with crashes,
                     failures, and orderings going wrong.)

           Step 2.  Walk the scenario through your design.
                    At each step, ask: "What does the system need here?"

           Step 3.  Aggregate "what's needed."
                    That's your minimal architecture.
                    Anything not in that list — delete.

That’s it. Three steps. No architecture-pattern library required. The scenario does the work for you.

Why this works (and why it’s hard to skip)

Three reasons:

1. AI optimizes for plausibility, not necessity. It lists components that sound right for this kind of system, drawing from its training data. It can’t know which components are necessary for your specific scenario, because it doesn’t see your scenario unless you walk it through.

2. Scenarios surface the negative space. A happy-path design is the union of every component someone might need. A scenario walk is the intersection of components someone definitely needs for that scenario. The intersection is always smaller — and more honest.

3. Scenarios surface what AI missed. The batch-rollback runtime wasn’t on AI’s list. It surfaced because scenario 3 was a state AI’s training data didn’t lean on. Whatever your system’s weird state is — only your scenarios will find it.

The reason this method is hard to skip is that the pressure to just accept AI’s design is enormous. The design looks complete. It uses real words. You feel productive saying “yes, build it.” Walking a scenario feels like slowing down. It is. That’s the whole point.

What’s next in this series

This is part 2 of the AI Collaboration Survival Guide. The previous post was about making AI’s claims about completed work auditable via a backlog database. The next ones, lining up:

Pain Coming up
AI edits one function, breaks 10 callers Code graph + impact analysis
AI modifies code it shouldn’t touch Governance hints as the only authoring surface
What did AI even change this week? Event ledger
Every session starts from zero Project memory layer

One pain per article. All built around the same open-source project, aming-claw.

About aming-claw

  • GitHub: amingclawdev/aming-claw
  • What it is: A shared workspace where you and your AI agent see the same dashboard. Backlog database, code graph, event ledger, governance hints — all queryable by AI through MCP.
  • Why I’m writing this series: I keep running into the same kind of AI-collaboration pain. Each post fixes one of them. The fixes generalize beyond aming-claw — the scenario-walk method in this post is a 5-minute habit you can adopt in any project.

If the parallel-agent scenario sounded familiar, drop a comment with the architecture decision AI most recently tried to oversell you on — I’ll work through it the same way in the comments. Free architectural review, basically. The repo also takes stars and they’re free for you to give. 🌟

Part 2 of “AI Collaboration Survival Guide” — practical patterns for the messy reality of shipping with AI agents.