My Profile Photo

Chang Min Park


Senior Software Engineer at Yahoo!



Making a Monorepo Navigable to Agents

Agents fail on layout, not IQ

Watch an agent on a large Android tree long enough and a pattern shows up. It invents a :app:assemble flavor that does not exist. It “fixes” a crash by editing files under build/ or generated/. It runs the root unit-test task that the team abandoned two years ago because it takes forty minutes and flakes. Then it declares done. The model was not uniquely dumb that day — the repo was illegible to tools that only know what you wrote down.

Intelligence without a map wastes tokens. The job is to make the monorepo reachable: one-shot commands, explicit forbidden paths, module boundaries in prose short enough to load — not a 10k-token novel nobody maintains.

This pairs with how we think about CI for Android: if humans need a pinned JDK and a real pipeline command, agents need the same, discoverable in one hop.

What “navigable” means

An agent (or a new hire) should answer these without archaeology:

Question Bad answer Good answer in-repo
How do I unit-test module X? “Gradle somewhere” ./gradlew :feature-mail:testDebugUnitTest
What is generated? Silence build/, *Generated*, Room/Schema folders — do not edit
Where does feature Y live? Search the universe Module map: feature → Gradle path → owners
What must never ship from chat? Vibes Secrets paths, Play keys, internal metric names

If those answers live only in Slack lore, every agent session relearns them wrong.

flowchart TB
  root[AGENTS.md — commands + bans]
  root --> feat[feature-mail/AGENTS.md]
  root --> shared[core-ui/AGENTS.md]
  root --> rules[".cursor/rules — glob-scoped"]
  feat --> cmd["./gradlew :feature-mail:testDebugUnitTest"]
  shared --> ban[Do not edit build/ or generated]
  rules --> compose[Compose rules on ui/**]

Figure 1. Thin root instructions; nested playbooks and glob rules for local truth — not one giant always-on essay.

One-shot commands beat narrative

Put the commands you actually run in CI near the top of AGENTS.md (or equivalent). Prefer copy-paste lines over paragraphs:

# Module unit tests (PR gate shape)
./gradlew :feature-mail:testDebugUnitTest

# Static analysis the team enforces
./gradlew :feature-mail:detekt

# Do not: ./gradlew test  (root suite — slow, not the PR gate)

Agents pattern-match on executable snippets. A sentence that says “run the appropriate module tests” invites improvisation. The same discipline belongs in skills and runbooks for recurring workflows: “add a Compose screen in :feature-X” should list files, packages, and the verify command — Medium Engineering’s Android skills writeup makes that case well for team playbooks.

Generated folders look editable

To a model, FooDto_Impl.kt is just another Kotlin file with a helpful name. Your rules must say do not edit generated sources and name the directories. Pair that with harness checks if you evaluate agents: a golden task that fails when build/ appears in the diff (eval as ship bar).

Also call out:

  • local.properties / signing material — read-only or out of bounds
  • Screenshot and goldens folders — update only via the approved test task
  • Vendored or generated GraphQL/Apollo sources — regenerate, do not hand-patch

AGENTS / rules without a 10k novel

Always-on context is a budget. A 10k-token root file that restates Clean Architecture will be half-ignored and half-overfitted. Split by job:

  • Root AGENTS.md — setup, global bans, canonical commands, link to module map
  • Nested AGENTS.md — per feature or package conventions that apply when working in that subtree
  • Glob-scoped rules (e.g. Cursor .mdc) — Compose, ViewModel, or test patterns that attach only when matching files are in play
  • On-demand skills — multi-step runbooks loaded when the task matches, not on every chat

Medium Engineering described the evolution from one heavy AGENTS.md to scoped rules so the model gets the right playbook at the right time. Cursor’s docs for rules and AGENTS.md match that shape: portable repo instructions plus scoped overrides.

Rule of thumb - if a paragraph has not prevented a real wrong edit in the last quarter, cut it; agents do not need your manifesto.

Module boundaries on paper

Large Mail-style clients are graphs of Gradle projects. Write a short module map: feature name, Gradle path, what it may depend on, what must not depend back. Agents routinely “help” by introducing a dependency cycle or reaching into another team’s internals because the graph was implicit. You do not need a full architecture book — a table and a “preferred public API packages” line save more thrash than another essay on MVVM.

Wrap-up

Make the monorepo legible the way you make CI honest: one-shot commands, named forbidden paths, thin always-on rules, deeper playbooks on demand. Agents are not lost because they lack a bigger model; they are lost because the map was never checked in. Fix the map first — then judge the model.

References