Image showing What I Found in the Pilotflow Codebase Before Writing a Line of New Code

What I Found in the Pilotflow Codebase Before Writing a Line of New Code

affiliate best offer

[!note] 📚 Pilotflow Series: Building a Gmail Addon

  1. The $50,000 Lie That Almost Killed My Gmail Addon — June 8
  2. Gmail OAuth Scope Tiers Decoded — June 15
  3. Pre-Development Codebase Analysis ← you are here
  4. Legal Documents for Gmail Addons — June 29

The scope decision was made. The OAuth analysis from the previous post pointed clearly to gmail.addons.current.message.readonly — sensitive, not restricted, no CASA required. Time to write code.

Except I didn’t write code. I read it first.

The Pilotflow repository existed in a partially-built state from earlier work. My first instinct was to pick up where the last commit left off and start adding features. My second, better instinct was to understand what I’d be building on top of before adding anything.

That decision, which felt slower in the moment, was actually faster. The review surfaced three findings that would have been significantly more expensive to discover post-implementation.


The Branch Situation

The first thing a codebase review has to answer: what is the actual state of this code? Not “what does the README say,” but what exists on every branch, what’s complete, what’s half-built.

The main branch had one OAuth scope and basic email labeling. The development branch — named backup-code-20260202, which is not a confidence-inspiring name — had 4,146 additional lines: an email processor with forwarding and batch actions, a server utilities module, a full dashboard UI, and an end-to-end test framework.

It also had seven OAuth scopes, versus one on main.

Neither branch was “right.” The main branch was the source of truth for production but behind on functionality. The development branch had features that weren’t on main and had never been reviewed against the scope analysis.

Merging blindly would have introduced one of two problems: regression (losing development branch features if they didn’t make it through the merge) or scope bloat (requesting permissions for features not yet needed). Understanding both branches first made the merge decision obvious rather than a coin flip.

Takeaway: Before any non-trivial development starts, document the state of every active branch. The most dangerous assumption in codebase archaeology is that main reflects the full project.


The Reprocessing Bug

The second finding was the one that mattered most.

Pilotflow’s core mechanic is a processing engine: scan the inbox, apply rules to matching emails, label processed messages so they’re not processed again. The label was pilotflow-processed. The logic checked whether this label was present before touching any email.

This looked correct in isolation. It wasn’t.

The bug: replies create new messages in the same thread. When someone replies to a Pilotflow-processed email, the reply arrives as a new message — without the pilotflow-processed label. The engine then scans the thread again, encounters the unlabeled reply, and processes the entire thread — including the original message it had already handled.

The result was silent duplicate processing. Not a crash. Not an error log. Just the same email acted on twice, or three times, depending on how many replies came in. For a tool that archives, labels, or forwards email, duplicate processing isn’t a performance problem — it’s a correctness problem that affects user data.

The bug was only visible when tracing the full lifecycle:

Email arrives
  → Processed by Pilotflow
  → Labeled "pilotflow-processed"

Reply arrives to same thread
  → New message, no "pilotflow-processed" label
  → Thread re-examined by Pilotflow
  → Original processed message re-encountered
  → Processed AGAIN

The chain of events that causes the problem looks completely reasonable at each individual step. That’s what makes this category of bug hard to find by reading the feature code alone — you have to trace the lifecycle, not just the function.

The architectural fix was clear once the bug was identified: track processed thread IDs, not message IDs. Once a thread has been processed, skip it entirely on subsequent scans, regardless of what new messages arrive. The thread-level label replaces the message-level label as the idempotency mechanism.

[!note] Why this matters for new features The batch-action features being added in the development branch would have inherited this bug. An action that runs once per thread would have run once per reply. Finding this during the review — before implementing the batch actions — prevented the bug from being baked into the new code’s assumptions.


The Notiwise Framework

The third finding was the positive one.

Before Pilotflow, there was Notiwise — a Google Workspace calendar addon. Building Notiwise required figuring out a complete launch path: OAuth scope selection, legal document creation, OAuth consent screen configuration, demo video structure, Workspace Marketplace submission requirements. Twelve phases of work, documented carefully in the project file.

When I opened the Pilotflow repository, that framework was sitting in the vault, ready to reuse.

Pilotflow’s launch path was structurally identical to Notiwise’s. Same platform. Same regulatory environment. Same sequence of decisions. Reusing the Notiwise framework for Pilotflow’s planning saved an estimated 8–12 hours of re-figuring the same questions from first principles.

This is what compound interest looks like in project work. The two hours spent documenting the Notiwise launch process didn’t produce documentation — they produced a reusable asset that makes every subsequent Google Workspace addon faster and more reliable to build. Not because the documentation is consulted occasionally, but because it encodes decisions that don’t need to be made again.

Takeaway: Process documentation from a previous project is a productive asset, not a compliance artifact. The value shows up on the next project — but only if the documentation was specific enough to actually reuse, not just general enough to feel complete.


What the Review Changed

Before the review, the plan was: open the development branch, pick up where it left off, start adding features.

After the review, the plan was different:

  1. Merge the development branch — the features were worth including, the scope additions justified by the feature inventory
  2. Fix the reprocessing bug first — before touching any new code, establish correct thread-level idempotency
  3. Use the Notiwise framework — apply the 12-phase launch checklist directly to Pilotflow’s launch planning

The review cost one focused day. It prevented at least two compounding problems from being built into the foundation, and it eliminated a week of planning work by reusing an existing framework.

The instinct to read before writing feels unproductive when you’re eager to build. It’s one of the more reliable productivity investments in software work.


A Checklist for Pre-Development Reviews

If you’re building on existing code:

  • Read every active branch — don’t assume main is complete
  • Inventory existing features: what’s complete vs. partial vs. started-and-abandoned
  • Trace core workflows end-to-end before extending them — the bug is usually in the lifecycle, not the function
  • Look for what the existing code assumes, not just what it does
  • Search for reusable frameworks from structurally similar past projects

The next step after the review: making Pilotflow legally publishable. Google requires a Privacy Policy and Terms of Service before the OAuth consent screen can be configured.

→ Next: Legal Documents for Gmail Addons in 15 Minutes

Full Bright

Full Bright

A professional and sympathic business man.

Contact

Contact Us

To order one of our services, navigate to the order service page

Address

10 rue François 1er,
75008 Paris

Email Us

hello at bright-softwares dot com

Open Hours

Monday - Friday
9:00AM - 05:00PM