living-architecture
A Claude Code plugin (la) plus its command-line tools for spec-driven
development with an enforced living architecture:
- Spec flow —
/la:specruns a change through four resumable stages (plan → failing tests → implementation → review loop), keyed on the Linear issue whose branch name matches the current branch, with OpenSpec as the behaviour corpus. - Living architecture — one LikeC4 model, arc42 principles per node, and
la-arch-check, which enforces the model as the repo's single import law and cross-checks code, model, docs, and specs. - Review processing —
/la:process-reviewswaits for CI and review bots, then triages CI failures, Codex, and (when enabled) CodeRabbit and SonarQube findings into one fix plan. - Deterministic refactoring — rope-driven renames and moves whose completeness is proven by the type checker, not trusted.
Install
# the plugin
/plugin marketplace add MotleyAI/living-architecture
/plugin install la@living-architecture
# the commands (la-*, dr-*), pinned to the same version as the plugin
uv tool install living-architecture==0.1.1
Skills run la-doctor --expect <version> first and stop if the installed
commands don't match the plugin.
Prerequisites: git, bash, gh (authenticated), jq; npx for the
OpenSpec and LikeC4 CLIs; the Linear MCP server for the spec flow; the Codex MCP
server (mcp__codex__codex) for plan, test, and diff reviews; the SonarQube MCP
server if Sonar is enabled; and a type checker in the target repo (the
refactoring and architecture gates compare against its recorded baseline).
Skills
| Skill | Purpose |
|---|---|
la:spec |
Entry point: rehydrate the Linear issue, detect the stage, dispatch |
la:spec-plan, la:spec-tests, la:spec-implement, la:spec-review |
The four stages |
la:openspec-init |
Initialize or repair OpenSpec in a repo |
la:living-architecture |
Set up or maintain the architecture layer |
la:arch-slice |
Retire a batch of #legacy import arrows with verified moves |
la:process-reviews |
Triage CI, Codex, CodeRabbit, and Sonar feedback into a plan |
la:fetch-coderabbit-threads, la:fetch-failed-pr-checks, la:reply-to-pr-thread |
Single-source review helpers |
la:codex-review |
Codex review of the current diff |
la:concise-comments |
Comment/docstring rules and a trimming pass |
la:deterministic-refactor, la:make-diff-compliant, la:make-refactor-target-compliant |
Verified refactoring |
Commands
| Command | Purpose |
|---|---|
la-doctor |
Check tool/plugin versions, the repo config, and git/gh |
la-config get <key> / la-config show |
Print resolved repo config |
la-arch-check |
Architecture cross-check (exit 0 OK, 1 findings, 2 broken setup) |
la-arch-diagrams |
Regenerate the mermaid view diagrams embedded in arc42 docs |
la-check-conventions <PR> / --base BRANCH |
Imports-at-top and text-ratio gate on changed .py files |
la-count-comments |
Count comment/docstring lines, or the net change vs a git ref |
la-wait-for-reviews <PR> |
Wait for CI and the CodeRabbit review to settle |
la-fetch-failed-pr-checks <PR> |
Failed checks plus their failed-step logs |
la-fetch-coderabbit-threads <PR> |
Unresolved CodeRabbit threads, nitpicks, outside-diff comments |
la-reply-to-pr-thread, la-reply-invalid-coderabbit |
Reply to a review thread (body on stdin) |
dr-refactor, dr-compliance, dr-mock-lint |
See Deterministic refactoring |
Repo config
Optional living-architecture.yaml at the repo root; without it every value
takes its default.
reviewers:
coderabbit: false # CodeRabbit steps and commands run only when true
sonar:
enabled: false # SonarQube steps run only when true
project_key: my-org_my-repo # required when enabled
issue_key_pattern: "[A-Z][A-Z0-9]+-\\d+" # ids allowed in arc42 [target: …] tags
commands:
test: pytest -m "not integration" # the full suite the flow runs; unset = the repo's documented one
lint: ruff check .
conventions:
text_ratio_max: 0.15 # max share of comment/docstring-only lines
exempt: [] # repo-relative globs skipped by la-check-conventions
Architecture checks in CI
Pin the checker to a release; it needs no per-repo code beyond
architecture/. --no-build installs only prebuilt wheels:
- uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
- run: uvx --no-build --from living-architecture==0.1.1 la-arch-check
Working from a local checkout
To use and edit the plugin at the same time, run everything from a clone instead of a marketplace install:
git clone https://github.com/MotleyAI/living-architecture ~/src/living-architecture
uv tool install -e ~/src/living-architecture
alias claude='claude --plugin-dir ~/src/living-architecture/plugin' # e.g. in ~/.bashrc
- Do not also install
lafrom the marketplace — both copies would load and every skill would appear twice. If it is installed,/plugin uninstall la@living-architecturefirst. - Python and bash edits take effect on the next command run (editable install).
Adding or renaming a command in
pyproject.tomlneedsuv tool install -eagain. - SKILL.md edits take effect from the next Claude Code session.
- Launchers that don't read your shell aliases (IDE or git-client integrations)
need
--plugin-dir <checkout>/pluginadded to their own command settings. - To try an unreleased checker in a repo that pins a release,
pip install -e <checkout>into that repo's environment; its next dependency sync restores the pin.
Releasing
Bump the version with uv version <new>, then in plugin/.claude-plugin/plugin.json
and every skill's la-doctor --expect pin (the tests fail until all agree), and
update the pins in this README. Tag v<version> and publish a GitHub release for
it; the Publish to PyPI workflow uploads the package (it refuses a tag that
doesn't match the package version).
Deterministic refactoring
Rename and move Python code with automatic import/reference rewriting — and, the actual point, a deterministic check that the refactor left nothing dangling.
The rename tool (rope) is best-effort: no refactoring tool reliably rewrites
every type-annotated obj.attr, super() call, and subclass override. So it is
never trusted — it is verified. A strict type-check proves no dangling static
reference remains; @typing.override turns a missed override into an error; a
mock-spec lint turns a missed dynamic (mock) reference into a failure. Green ⇒
provably no dangling reference.
Tools:
dr-refactor— rope mutator:rename/move-symbol/move-moduledr-mock-lint— fail on mocks not bound to a specdr-compliance— report the constructs that make a refactor un-verifiable
What a fully compliant repo must fulfill
A repo is refactor-verifiable when a missed rename is guaranteed to surface as a failing check. That holds only when:
- Target code is typed. Functions annotated (params + return), class
attributes annotated, and every variable/parameter that holds an instance of
a class annotated. An unannotated
x.attris unresolvable, so a miss there is invisible — determinism is bought with type coverage. (dr-compliance+ RuffANN*enforce this.) - A type checker runs against the project's own environment. mypy or basedpyright resolving imports via the project venv — the same interpreter the tests use — passing, or at a recorded baseline.
- Overrides are marked.
@typing.overrideon every override, withreportImplicitOverride(basedpyright) or mypy strict enabled, so a base rename that orphans an override is an error, not a silent break. - Mocks are spec-bound. No bare
Mock()/MagicMock()/patch(); every double bound viaspec_set=/autospec=True/ aProtocolfake. A stale mock member then fails (AttributeError, or a type error for typed fakes). (dr-mock-lintenforces this.) - The gate is wired into CI/pre-commit. type-check (no new errors vs
baseline) +
dr-mock-lint+ the test suite, on every change.
dr-compliance mechanically checks 1, 3-adjacent (via the type checker), and 4,
and reports each violation as file:line: <kind>: <message>.
Using it on an existing repo
1. One-time setup
-
Install the tools (see Install above).
-
Add a type checker to the project's dev dependencies, pointed at its venv — it must resolve imports the way the tests do:
# pyproject.toml [tool.basedpyright] venvPath = "." venv = ".venv" pythonVersion = "3.11" typeCheckingMode = "standard" # already errors on attribute access reportImplicitOverride = "error"
(Equivalently
mypy --strict --python-executable .venv/bin/python.) -
Add
dr-mock-lint <tests>and the type checker to.pre-commit-config.yamland CI. Record the current type-error set as the baseline — you do not need a clean whole repo, only "no new errors" per change.
The mutator (rope) does not belong in the project's dependencies — it
reads source and needs nothing installed. Only the verifier needs the env.
2. Keep every PR compliant — skill make-diff-compliant
Bring exactly the files a PR touches up to the five conditions before it merges,
so compliance grows monotonically with the diff instead of requiring a big-bang
migration. The skill runs dr-compliance on the changed files, adds the missing
annotations / @override / mock specs, and loops until the type checker and
dr-mock-lint are clean on the diff. See plugin/skills/make-diff-compliant/.
3. Do a refactor — skill deterministic-refactor
Locate the symbol with the editor/LSP → dr-refactor dry-run → apply → run the
gate (type checker shows no new errors, dr-mock-lint passes, tests pass, grep
the string-only references no static tool sees) → review the diff. See
plugin/skills/deterministic-refactor/.
4. Make a refactor's blast radius compliant first — skill make-refactor-target-compliant
Before renaming X or X.attr, close the blind spots the gate would otherwise
miss: code that might reference the target but is currently invisible to the
checker — untyped parameters/variables that could hold an X, classes whose
attribute names match the target ("right-looking" names), subclasses missing
@override. The skill drives dr-compliance --attr <name> to enumerate those
sites, annotates them, and re-checks until the blast radius is fully typed —
so the post-rename gate is sound. See plugin/skills/make-refactor-target-compliant/.
Release files for living-architecture 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| living_architecture-0.1.1.tar.gz | 43.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| living_architecture-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 97.8 kB
Release files / living_architecture-0.1.1.tar.gz
| Download URL | living_architecture-0.1.1.tar.gz |
|---|---|
| Size | 43.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
268802e44fc0e3b9e926c31d4db3ff0938b7dd59aab3b07a571fb62331517c8b
|
|
BLAKE2b-256 checksum How to use checksums |
ff4c864c2231b954b6af0a27850052e644e8e4468d761322cd16769e453f2477
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 26, 2026.
Transparency logRelease files / living_architecture-0.1.1-py3-none-any.whl
| Download URL | living_architecture-0.1.1-py3-none-any.whl |
|---|---|
| Size | 54.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
56cbf88273615c915f27d1eca2a4576e9e50b888f171f1d8313f829a1f075b2e
|
|
BLAKE2b-256 checksum How to use checksums |
1ca2faa94cf9289999741c531ae3466ee7794507f8650bae593096b351074bd2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 26, 2026.
Transparency log