szpak

The Map Is Not The Architecture

A practical tutorial about using import edges, path tags, and modwire evidence to make architecture rules visible before a coding agent crosses boundaries.


Peter had the first rule in place. The assistant now knew where to start, what to read, and what kind of route receipt it had to report before editing. That was already better than reviewing a surprise diff after the damage was done, but it was still mostly words.

The rule said that reports may ask customers for risk data through a public query. It also said that reports may not import customer internals. This was clear to Peter, and it was clear to the team after a short conversation. The problem was that the repository needed a way to show when the line was crossed.

Otherwise, the rule would slowly become another polite sentence that everyone agrees with and nobody notices until review.

Act I. Peter Draws The Line

Peter opened the local reports rule and wrote the important part again, this time with less explanation:

Reports may ask Customers for risk data through a public query.
Reports may not import customer internals.

Then he looked at the code. Ledger House had a familiar shape:

src/
  customers/
    application/
    internal/
    public/
  reports/
    application/
    ui/
  audit/
    application/
    public/

This was useful. Not perfect, but useful. The folders already carried some architectural meaning. customers/public was meant to be used from outside. customers/internal was not. Reports had a UI part and an application part. Audit had a public seam.

Peter did not need a philosophical discussion to detect the first bad import. He needed the repository to notice when a file under reports imported a file under customers/internal.

That is not the whole architecture. It is only a visible edge. But sometimes a visible edge is enough to start the right conversation.

Act II. Modwire Under The Floor

This is where modwire enters the story. Do not give it a cape. It does not understand Ledger House’s business strategy, compliance pressure, or why Finance always remembers the CSV export one day before the meeting. It does something smaller and more useful for this problem: it looks at code structure.

  • files become nodes;
  • imports become edges;
  • paths can become architectural tags;
  • dependency direction can be checked;
  • cycles and backward flow can be made visible.

This is enough for enclosure to ask a very practical question:

Did reports import something it should not import?

That question is boring in the best possible way. It does not replace Peter’s judgment. It gives Peter evidence.

Structural Evidence

Architects often speak in concepts: ownership, seams, modules, layers, contexts, policies, dependencies. These words matter, but code does not always speak them directly. Code speaks through files, imports, calls, names, and folders.

Structural evidence is the bridge between the two.

If the team says customers/internal is private, and a report imports it, the tool does not need to understand customer risk. It only needs to show the edge:

reports/application/customer-risk-export.ts
  -> customers/internal/risk-score.ts

That edge does not automatically prove what the correct design should be. Maybe reports are wrong. Maybe customers are missing a public query. Maybe the folder names no longer match reality. All of these are different conversations.

But without the edge, the conversation starts too late and too softly.

The First Map

Peter started with a small enclosure.yaml shape:

architecture:
  root: src
  boundaries:
    tags:
      - { name: customers, match: "customers/**" }
      - { name: customer-internal, match: "customers/internal/**" }
      - { name: customer-public, match: "customers/public/**" }
      - { name: reports, match: "reports/**" }
      - { name: audit-public, match: "audit/public/**" }

This is not a full model of Ledger House. It is not supposed to be. Peter only tags what he needs for the current rule. The goal is not to describe the whole city in one sitting. The goal is to mark the road that should not be used.

Then he writes the rule in the same language:

architecture:
  root: src
  boundaries:
    tags:
      - { name: customers, match: "customers/**" }
      - { name: customer-internal, match: "customers/internal/**" }
      - { name: customer-public, match: "customers/public/**" }
      - { name: reports, match: "reports/**" }
    rules:
      - {
          source: "reports/**",
          disallow: ["customers/internal/**"],
          allow: ["customers/public/**"],
        }

The exact configuration can grow later. For now, the point is simple: reports may use the public customer seam, but not the customer internals.

Reading A Violation

Now imagine the assistant tries the first version of the CSV export again and creates this import:

import { calculateRiskScore } from "../../customers/internal/risk-score";

The tool reports a boundary violation. Peter should not read that as a court sentence. He should read it as evidence that a design question must be answered.

The question is:

Is this dependency wrong, or is the public seam missing?

This matters. Sometimes the assistant is wrong because it ignored the boundary. Sometimes the assistant is showing that the architecture has a missing door.

If reports truly need customer risk data, then customers probably need to expose something like this:

customers/public/customer-risk-query

After that, reports can depend on the public seam and the rule still holds. The architecture did not block the feature. It forced the feature to use the right conversation between modules.

Do Not Worship The Map

Peter is careful with this part, because architecture tools can make people strange. Once a graph appears on screen, someone will start treating it like the system itself.

The map is not the architecture.

The architecture is the set of decisions about ownership, change, dependency, and responsibility. The map only shows traces of those decisions in code. It can show that reports imported customer internals. It cannot tell Peter whether the business should move risk scoring into customers, reports, compliance, or a new module. That is still design work.

This distinction keeps the tool useful. The graph is a receipt, not a judge.

Peter wants the assistant to use the evidence before editing and after editing. Before editing, the assistant should read the rule and name the allowed seam. After editing, it should run the check and report whether the edge exists. That is cooperation.

What The Assistant Should Say

For the customer risk export, the route receipt now becomes more concrete:

Route read:
- Files: .enclosure/rules/INDEX.md, .enclosure/rules/shared/INDEX.md,
  .enclosure/rules/local/reports.md
- Reason: report export needs customer risk data and audit data.
- Stop point: reports rule names forbidden customer internals.
- Owner: reports owns export orchestration.
- Public seam: customers/public/customer-risk-query.
- Dependency direction: reports may call customer public seam only.
- Checks to run: boundary check and report export tests.

If the assistant cannot name the public seam, it should stop. That is not a failure. That is exactly the moment where Peter wants the assistant to ask:

I found no public customer risk query. Should I add one to customers/public, or
is there an existing seam I missed?

This is much better than guessing.

A Small Exercise

Choose one dependency that often appears in review. Do not start with the whole architecture. Start with one boundary.

Write it in plain language first:

This part may use:
This part may not use:
The public seam is:
Stop and ask when:

Then check whether your file paths already contain enough signal to express it:

orders/internal/**
orders/public/**
reports/**
ui/**
infrastructure/**

If the paths carry meaning, you can probably tag them. If they do not, that is also useful information. It means the repository may be hiding architecture in names that only humans remember.

Finally, ask the assistant to report the expected dependency before editing. If it cannot name the public seam, do not let it improvise.

Summary

Rules are better than folklore, but rules become much stronger when the repository can show evidence. modwire gives enclosure enough structure to see files, imports, tags, and dependency direction. That does not make it a compiler, a modeler, or an architect. It makes it a useful witness.

The important question is not “what does the graph say?” The important question is what the graph helps Peter ask:

Is this dependency wrong, or is the public seam missing?

In the next tutorial, Peter will take the repeated review comment and split it properly: the deterministic part becomes a check, and the unclear part becomes a human question before editing starts.