Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

contract-tree

Stars License: MIT Last commit Issues Author: nicolasapr

A Claude Code plugin that represents a project as a tree of documented modules with boundary contracts, so a coding agent stays oriented in large codebases — reading a few targeted contracts instead of scanning everything, and turning any boundary change into a deliberate preserve-vs-cascade decision.

The problem

As a project grows, agents lose track of how modules fit together. A change to one module ripples into others the agent can't see, so it either breaks downstream consumers or over-reads the whole tree to be safe — both waste context and produce fragile changes.

The idea

Each module (a directory) carries a CONTRACT.md declaring its purpose, I/O, upstream dependencies, invariants, and code entrypoints. A repo-root .contract-tree/tree.md index holds the resolved dependency graph, so the agent can compute what depends on what with a single read.

When the agent is about to change a module, it:

  1. reads the contract to see the module's boundary,
  2. checks whether the change stays inside the boundary or touches it,
  3. if it touches, computes the blast radius (all downstream modules that would break),
  4. and asks you to choose: preserve the boundary or cascade the change.

The agent never cascades on its own.

Grounding

The model is a thin, agent-facing application of established practice: a CONTRACT.md is a Design-by-Contract spec (precondition / postcondition / invariant); a module boundary is where information hiding puts a design decision likely to change; a boundary change is classified by backward compatibility the way SemVer distinguishes major/minor/patch; the blast radius is change impact analysis (candidate vs actual impact set); how strongly a consumer depends on the changing output is read as connascence; and "preserve" is consumer-driven evolution — letting a provider change without every consumer jumping at once. The full mapping, including the compatibility rule and the connascence ladder, is in skills/contract-tree/references/principles.md.

The skills

Skill When it fires
contract-tree Router. Explains the model and points to the right sub-skill. Always loaded, stays light.
map-modules Bootstrap a contract tree — extract contracts from existing code, or design a module tree greenfield before writing code.
change-with-contracts About to change code. Locates the module, classifies the change, computes the blast radius, and requires an explicit preserve-vs-cascade decision.
check-drift Audit whether contracts still match the code (e.g. after a large merge). Report-only, never auto-fixes.

On-disk format

Per-module CONTRACT.md (source of truth):

---
id: gps/fix-parser
path: src/gps/fix-parser
entrypoints:
  - src/gps/fix-parser/index.ts:parseFix
upstream: [gps/nmea-reader]
io:
  input: "validated NMEA sentence (NmeaSentence)"
  output: "Fix { lat, lon, alt, hdop, ts }"
---

## Purpose
Convert validated NMEA sentences into a normalized Fix.

## Invariants
- Coordinates always WGS84 decimal degrees.
- `alt` in meters.
- Never returns a partial Fix: either a complete Fix or a thrown error.

Repo-root .contract-tree/tree.md (regenerable index; A → B means B is downstream of A):

# Contract Tree
> Source of truth for I/O = the CONTRACT.md files.

- gps/  — location service
  - gps/nmea-reader        → gps/fix-parser
  - gps/fix-parser         → gps/track-store, gps/geofence
  - gps/track-store        → (leaf)
  - gps/geofence           → (leaf)

Only upstream is authored; downstream is derived by inverting it. If the index and a contract disagree, the contract wins. Full spec: skills/map-modules/references/contract-format.md.

Install

/plugin marketplace add nicolasapr/contract-tree
/plugin install contract-tree@contract-tree

Then, in a project:

  • No tree yet? Ask to map the modules for the area you're working in.
  • Changing code? The change-with-contracts flow computes the blast radius and asks before touching any boundary.

Example (GPS)

The runnable example in fixtures/gps/ is a small GPS pipeline — nmea-reader → fix-parser → {track-store, geofence} — with a CONTRACT.md per module and a .contract-tree/tree.md.

Worked scenario: changing fix-parser's output Fix.alt from meters to feet is a boundary change. The blast radius is {track-store, geofence} — both consume alt — so the agent surfaces those two modules and asks preserve-vs-cascade before editing. See fixtures/gps/VALIDATION.md for the mechanical validation of all three flows.

Run the fixture's own tests:

cd fixtures/gps && npm install && npm test

License

MIT — see LICENSE.

About

Claude Code plugin: represent a project as a tree of documented modules with boundary contracts, so an agent stays oriented in large codebases and makes boundary changes a deliberate preserve-vs-cascade decision.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages