improve-codebase-architecture

star 2

Find deepening opportunities in the ELI PANDA codebase, informed by the domain glossary in `docs/CONTEXT.md`, the per-feature pages in `docs/technical/`, the ADRs in `docs/adr/`, and the conventions in `CLAUDE.md`. Use when the user wants to improve architecture, find refactoring opportunities, consolidate tightly-coupled modules, or make the codebase more testable and AI-navigable.

eli-eric By eli-eric schedule Updated 5/18/2026

name: improve-codebase-architecture description: Find deepening opportunities in the ELI PANDA codebase, informed by the domain glossary in docs/CONTEXT.md, the per-feature pages in docs/technical/, the ADRs in docs/adr/, and the conventions in CLAUDE.md. Use when the user wants to improve architecture, find refactoring opportunities, consolidate tightly-coupled modules, or make the codebase more testable and AI-navigable.

Improve Codebase Architecture

Surface architectural friction in this codebase and propose deepening opportunities — refactors that turn shallow modules into deep ones. The aim is testability and AI-navigability.

Glossary

Use these terms exactly in every suggestion. Consistent language is the point — don't drift into "component," "service," "API," or "boundary." Full definitions in LANGUAGE.md.

  • Module — anything with an interface and an implementation (a function, a hook, a .cont.tsx/.comp.tsx pair, a Zustand store, a feature folder under src/modules/, a server-side helper).
  • Interface — everything a caller must know to use the module: types, invariants, error modes, ordering, config. Not just the TypeScript signature.
  • Implementation — the code inside.
  • Depth — leverage at the interface: a lot of behaviour behind a small interface. Deep = high leverage. Shallow = interface nearly as complex as the implementation.
  • Seam — where an interface lives; a place behaviour can be altered without editing in place. (Use this, not "boundary.")
  • Adapter — a concrete thing satisfying an interface at a seam.
  • Leverage — what callers get from depth.
  • Locality — what maintainers get from depth: change, bugs, knowledge concentrated in one place.

Key principles (see LANGUAGE.md for the full list):

  • Deletion test: imagine deleting the module. If complexity vanishes, it was a pass-through. If complexity reappears across N callers, it was earning its keep.
  • The interface is the test surface.
  • One adapter = hypothetical seam. Two adapters = real seam.

This skill is informed by PANDA's technical docs. They give names to good seams and record decisions the skill should not re-litigate.

Project context this skill relies on

  • docs/CONTEXT.md — cross-cutting domain glossary. The first place to look when naming a deepened module. Authoritative names; full definitions live on the per-feature pages it links to.
  • docs/technical/app-architecture.md — stack, module layout, request lifecycle, deprecated/legacy clusters, maintenance recommendations. Read this first when proposing cross-cutting refactors.
  • docs/technical/<feature>.md (e.g. orders-and-order-items.md, catalogue-and-items.md, permissions-model.md, systems-family/*.md) — per-feature domain vocabulary and known integration points. Read the page covering the area you're touching before naming anything.
  • docs/adr/ — architecture decision records. Check this directory for prior decisions that would conflict with a proposed refactor. See docs/adr/README.md for when an ADR should be written.
  • CLAUDE.md — coding conventions, container/component split, toast/fetch/modal patterns.
  • .agents/skills/architecture/SKILL.md — canonical folder layout and file-naming rules. A deepening proposal that moves code must respect these or call out the deviation explicitly.

The ADR directory is intentionally lightweight today. Decisions also live in the Maintenance recommendations, Deprecated / legacy, Open questions, and 🔮 Planned sections of the per-feature pages and app-architecture.md — treat those sections as informal ADRs and promote them into docs/adr/ when a real decision crystallizes.

Process

1. Explore

Read docs/CONTEXT.md for vocabulary, the relevant docs/technical/ page(s) for the area, and app-architecture.md for anything cross-cutting. Scan docs/adr/ for any decision that touches the area. Note the existing Maintenance recommendations and Open questions in the technical pages — your proposals should either build on them or explain why they're wrong.

Then use the Agent tool with subagent_type=Explore to walk the codebase. Don't follow rigid heuristics — explore organically and note where you experience friction:

  • Where does understanding one concept require bouncing between many small modules?
  • Where are modules shallow — interface nearly as complex as the implementation?
  • Where have pure functions been extracted just for testability, but the real bugs hide in how they're called (no locality)?
  • Where do tightly-coupled modules leak across their seams?
  • Which parts of the codebase are untested, or hard to test through their current interface?

Apply the deletion test to anything you suspect is shallow: would deleting it concentrate complexity, or just move it? A "yes, concentrates" is the signal you want.

PANDA-specific friction patterns to look for

The codebase has recurring shapes that often produce shallow modules. Use these as prompts, not as a checklist:

  • .cont.tsx leaking into .comp.tsx — a "pure" component that still reads from a store, calls a mutation, or knows about GraphQL types. The container's interface is wider than it looks. Deepening usually means pulling logic back into the container (or a hook) and narrowing the props the .comp.tsx receives.
  • Hooks extracted for tests, then called from one place — a useXyz hook whose body is small and whose only caller is one container. The deletion test usually clears it.
  • Mutation glue around queryMutate — wrappers that re-throw, re-shape, or re-toast around an axios-shaped response. The duplication is locality begging to live behind toast.promise (see the toast skill) or a typed mutation helper.
  • Filter / table state spread across module store + useTableStateStore + URL params — three places to update when a filter is added. A deeper module owns the filter state and exposes a small read/write interface.
  • Modal duality — code that touches both useModalStore (legacy) and useDynamicModalStore (current). See app-architecture.md "Maintenance recommendations" #3; new proposals should pick the dynamic side.
  • fetchClient / axiosInstance / queryMutate's AxiosResponse<T> shape — three transports for the REST gateway. The interface is wider than the work needs (see app-architecture.md "Maintenance recommendations" #1).
  • Form module + Zod schema + RHF wiring repeated per feature — wizard steps, field-level Zod, RHF resolver bindings duplicated across src/modules/<feature>/components/. Look for a deeper "form module" the feature can instantiate.
  • GraphQL query + custom hook + container plumbing — a query is defined in queries/, a typed hook generated by codegen, then re-wrapped by a feature hook that adds one parameter. Often the codegen-generated hook is already deep enough.

These are pointers, not mandates. Use the deletion test before proposing any of them.

2. Present candidates

Present a numbered list of deepening opportunities. For each candidate:

  • Files — which files/modules are involved (use repo-relative paths like src/modules/orders/Orders.cont.tsx:42)
  • Problem — why the current architecture is causing friction
  • Solution — plain English description of what would change
  • Benefits — explained in terms of locality and leverage, and also in how tests would improve

Use docs/CONTEXT.md + docs/technical/ vocabulary for the domain, and LANGUAGE.md vocabulary for the architecture. If docs/CONTEXT.md (and docs/technical/orders-and-order-items.md) calls something an "order line," say "the order-line intake module" — not "the OrderItemHandler," not "the order-item service."

Existing decision conflicts: if a candidate contradicts an ADR in docs/adr/, or an item in a docs/technical/ page's Maintenance recommendations, Open questions, or Deprecated / legacy section, mark it clearly (e.g. "contradicts ADR-0007 — but worth reopening because…" or "contradicts app-architecture.md Maintenance rec #2 — but worth reopening because…"). Don't list every theoretical refactor those sources forbid.

Do NOT propose interfaces yet. Ask the user: "Which of these would you like to explore?"

3. Grilling loop

Once the user picks a candidate, drop into a grilling conversation. Walk the design tree with them — constraints, dependencies, the shape of the deepened module, what sits behind the seam, what tests survive. The companion grill-me skill describes the cadence.

Side effects happen inline as decisions crystallize:

  • Naming a deepened module after a concept that's not in docs/CONTEXT.md? Add a short entry to docs/CONTEXT.md (one or two lines + link to the per-feature page that owns the long definition). If the long definition doesn't exist yet, add it to the relevant docs/technical/ page (or app-architecture.md if it's cross-cutting). Don't invent terminology that lives only in code.
  • Sharpening a fuzzy term during the conversation? Update docs/CONTEXT.md and the per-feature doc right there. Vocabulary drift across docs is the most common cause of repeat re-suggestions.
  • User rejects the candidate with a load-bearing reason? Offer to record it as an ADR under docs/adr/, framed as: "Want me to record this as an ADR so future architecture reviews don't re-suggest it?" Use the template at docs/adr/0000-template.md. Only offer when the reason would actually be needed by a future explorer to avoid re-suggesting the same thing — skip ephemeral reasons ("not worth it right now") and self-evident ones. For ephemeral or open-ended rejections, an Open question entry in the per-feature docs/technical/ page is the right home instead.
  • Want to explore alternative interfaces for the deepened module? See INTERFACE-DESIGN.md.
  • Deepening crosses into a domain another skill already owns? Defer to it for the implementation shape: fetching for query/mutation hooks, toast for mutation feedback, modals for dialog/sheet wiring, tables for PandaTableV2, wizard for multi-step forms, architecture for where new files land. The architectural argument is still yours; the local pattern is theirs.
Install via CLI
npx skills add https://github.com/eli-eric/ELI-panda --skill improve-codebase-architecture
Repository Details
star Stars 2
call_split Forks 1
navigation Branch main
article Path SKILL.md
More from Creator