LAMP — Language-Agnostic Module rePresentation

May 18, 2026

A proposal for an intermediate representation that captures software modularity before code is generated.


1. Overview

1.1 Motivation

Agentic coding assistants generate code that compiles and passes tests. Depending on the model and context size, the generated code often lacks coherent modular structure and code hygiene.

The artifacts that feed generation don't address modularity.

Language-Agnostic Module rePresentation (LAMP) fills the gap with a reviewable artifact that commits to modular intent before code exists: what each module encapsulates and exposes, the capability contracts the agent must honor, and a modularity audit that gates generation rather than reviewing it afterward.

1.2 What LAMP is

LAMP sits between architectural component-level design and code. It captures a system's modular structure in a form reviewable before any implementation exists. The agent or human generating code is then constrained where it matters (module boundaries, encapsulation, observable contracts) and free where it doesn't (types, languages, data structures, concurrency). It also shrinks the context window, saving token costs.

LAMP serves two goals:

  1. Module Review: a target for human review and modularity auditing before code changes.
  2. Code Generation: a contract the agent honors when producing code and tests.

LAMP is part of a software development pipeline:


DESIGN
   → decompose into modules around encapsulated decisions
LAMP
   → generate implementation honoring the contracts
CODE

LAMP rests on four principles drawn from established modularity practice:

2. Document layout

A LAMP artifact is a directory of Markdown files.

lamp/
  capability.md        # capability registry
  modules.md           # All module manifests

A single file is the default because LAMP modules are small. When a system has many modules or capabilities and a single file grows unwieldy, split them across several files. Name a module file with a module prefix (e.g., module-<family>.md) to group related modules. Name a capability file with a capability prefix (e.g., capability-<family>.md).

3. The module specification

The module manifest answers three questions: what does this module hide, what does it offer, what does it need? Each module is a top-level section in modules.md, with these subsections in order. All are required.

# Module: <name>

## Encapsulates
The design decision or complexity this module hides. State it in
caller irrelevant terms.

## Provider Capabilities
Markdown links into the capability registry in `capability.md`, one per
line.

  - [issue-session](capability.md#capability-issue-session)
  - [resolve-session](capability.md#capability-resolve-session)
  - [revoke-session](capability.md#capability-revoke-session)

## Consuming Capabilities
Markdown links into the capability registry, one per line.
Dependencies are on capabilities, never on other modules directly.

  - [monotonic-clock](capability.md#capability-monotonic-clock)
  - [opaque-bytes-storage](capability.md#capability-opaque-bytes-storage)

3.1 Authoring rules

  1. Encapsulation is named in caller-irrelevant terms. "How sessions are stored, expired, and revoked" — good. "Uses Redis with TTL" — leaks.
  2. Capability names don't leak implementation. flush_to_disk() leaks; commit() doesn't. cache_evict() leaks; forget(handle) doesn't.
  3. Dependencies are on capabilities, not modules. Say opaque-bytes-storage, not PostgresStore.
  4. No types, signatures, or language idioms. Promise<Result<Session, Error>> is implementation.

4. The capability specification

Capabilities live in capability.md's registry. Each is declared once. The heading format is fixed. Module manifests link to capabilities by anchor, so the heading is part of the contract.

### capability: <verb-phrase-name>

Description: one sentence on what this accomplishes for a caller.

Inputs: Description of inputs.

Outputs: Description of outputs.

Requires: what must hold for the capability call to be valid.

Guarantees: what is true on successful completion.

Failure modes: caller meaningful error categories.

Providers: List one or more providers who implement the capability. The capability registry and module manifests form a navigable graph in both directions.
  - [<module-name>](modules.md#module-<module-name>)
  - [<module-name>](modules.md#module-<module-name>)

4.1 Authoring rules for capabilities

  1. Verb-phrased. "issue", "resolve", "find-by-prefix" — verbs. Nouns like session() are smells; usually a leaked data structure.
  2. Inputs and outputs by role, not type. "subject" and "handle", not string and UUID.
  3. Failure modes are caller-meaningful. "not-authorized" tells a caller something. "RedisTimeoutException" leaks.

5. A worked example

From a user requirement:

As a service, I want to issue, validate, and revoke session handles so I can recognize returning callers without rechecking credentials on every call.

Acceptance criteria:

  • Given a valid subject, when I issue a handle, resolving it returns the original subject.
  • Given a revoked handle, resolving it returns invalid.
  • Given an expired handle, resolving it returns invalid.
  • Two handles for the same subject are distinct and unguessable.

LAMP excerpts:

capability.md capability registry:

### capability: issue-session

Description: produces an opaque handle representing an authenticated subject.
Inputs:
  - subject: the principal the session represents
  - claims: caller-supplied attributes
Outputs:
  - handle: opaque reference
Guarantees:
  - The handle is valid until revoked or expired.
  - The handle is distinct from every previously-issued handle.
  - The handle is not guessable from prior handles.
Failure modes:
  - capacity-exhausted
Providers:
  - [SessionStore](modules.md#module-sessionstore)

### capability: revoke-session

Description: invalidates an issued handle.
Inputs:
  - handle: an opaque reference previously returned by issue-session
Guarantees:
  - After this returns, resolve-session(handle) returns invalid.
  - Subsequent revoke-session(handle) calls are accepted with no further effect.
Providers:
  - [SessionStore](modules.md#module-sessionstore)

modules.md (SessionStore section):

# Module: SessionStore

## Encapsulates
How sessions are stored, expired, and revoked. Whether storage is
in-memory, in a database, or encoded into the handle itself is hidden.
Whether revocation is push-based or pull-based is hidden.

## Provider Capabilities
- [issue-session](capability.md#capability-issue-session)
- [resolve-session](capability.md#capability-resolve-session)
- [revoke-session](capability.md#capability-revoke-session)

## Consuming Capabilities
- [monotonic-clock](capability.md#capability-monotonic-clock)
- [opaque-bytes-storage](capability.md#capability-opaque-bytes-storage)

← All posts

This is a personal blog. Views expressed here are my own and do not represent any employer, client, or organization.