n8n's root guide covers setup, package architecture, testing, and public contribution practices. Its architecture sections describe boundaries around persistence, encryption, and lint configuration. They name prohibited workarounds as well as the intended API, while command guidance accounts for memory limits, large logs, package-local checks, and shared runtime state in tests.
Quoted passages are verbatim. Open one to see it in the source.
01 / Architecture as narrative
Keep persistence behind domain methods
The TypeORM boundary requires use-case-named repository methods with plain inputs and domain-shaped results. Renaming imports or hiding query builders in services does not satisfy the boundary.
Source excerpt starting at line 244.
244- **Pattern:** when a query needs operators (`In`, `IsNull`, `LessThan`,245 `FindOptionsWhere`, …), put it behind a **use-case-named repository method**246 that takes plain parameters and returns domain-shaped values — not a generic247 `find(options)` passthrough.
02 / Ratchets
Prevent quiet downgrades of lint policy
Because lint runs with --quiet, a package-wide downgrade to warning would look configured while enforcing nothing. The file connects this to a shared rule and a shrinking debt baseline.
Source excerpt starting at line 283.
283raises rules to `error`, and blocks scoped to `files`. It must not turn a rule284down for the whole package: every lint script runs with `--quiet`, so a `warn`285enforces nothing and reads as if it did. The code-health rule286`lint-config-layering` enforces this, with existing debt in287`.code-health-baseline.json`, which only shrinks.
03 / Hard prohibitions
Explain irreversible key loss
The encryption section gives both the data consequence and the enforcement points for its no-deletion rule. Deactivation is the intended operation.
Source excerpt starting at line 307.
307- **Deployment keys are never deleted** — data encrypted with a key becomes308 unreadable without it. Deactivate keys instead; the repository's delete309 surface throws at runtime and the lint rule rejects call sites.
04 / Good and bad pairs
Show the direction of graph connections
A parent-node lookup needs an inverted connection map; a child lookup uses the original map. The worked code ties the shared helper to the data structure's indexing direction.
Source excerpt starting at line 201.
201**Key concept:** `workflow.connections` is indexed by **source node**.202To find parent nodes, use `mapConnectionsByDestination()` to invert it first.
05 / Context budgeting
Design setup output for constrained agents
The setup command caps memory and concurrency, writes logs, and always produces a machine-readable summary. The file explains how to inspect a run without loading all its output.
Source excerpt starting at line 71.
71hand. It chains them in one process, caps per-process memory and turbo72concurrency so a 6GB box doesn't OOM, streams all output to73`.agent-setup/<step>.log` (gitignored), and surfaces only a one-line summary74per step plus the tail of the failing log. A machine-readable75`.agent-setup/summary.json` is always written so a backgrounded run is76readable in a single shot — no polling, no scrolling logs.
n8n's file tells an agent how the codebase works. It cannot tell it which bug three customers hit this week. Modem keeps that context current and attaches it to the work.