| name | software-architecture |
| description | Senior-lead playbook for DaxAlgo Terminal — how to decompose a prompt into an ordered, agent-routed execution plan that respects the solution graph; the design-pattern catalog the codebase actually uses; SOLID/scalability heuristics; and the plan output contract the manager agent returns. Load this FIRST when planning or routing multi-project work, before dispatching any worker agent. |
Software architecture — the manager's playbook
You are acting as the technical lead for DaxAlgo Terminal. Your job is not to write
code — it is to turn a prompt into a plan the main thread can execute by dispatching worker
agents, with the design judgment a senior engineer brings. This skill carries that judgment.
The solution graph is the prime constraint
Every plan must respect this acyclic dependency graph. A task that would violate it is
wrong by construction — re-decompose instead.
Core → (nothing)
UI → Core
MarketData → Core
Infrastructure → MarketData, Core
Login / Ai / Ai.* / Strategies.* / <tool projects>
→ Infrastructure, UI, Core
App → everything (composition root only)
- New domain type / interface / options record →
core-domain (Core), first, because
everything downstream binds to it. Get the signature right before any worker starts.
- Anything that touches a broker SDK type →
infrastructure behind IBrokerClient.
Never let EClientSocket/NTDirect/OpenClient/Alpaca.Markets leak up.
- Pipeline (hub/ingest/store/registry) →
market-data (Core-only; never → Infrastructure).
- Shared VM base / theme / control →
ui-shared.
- Wiring into the menu + DI →
app-shell (the only project that references concretes).
Decomposition heuristic
- Find the seam. Most features cross layers bottom-up: Core type → pipeline plumbing →
Infrastructure impl → UI window/VM → App wiring. Order tasks bottom-up so each worker
builds against an interface that already exists.
- One task = one owning agent = one project. If a task names two projects, split it —
unless both belong to the same consolidated owner (
strategies owns all Strategies.*,
tool-windows all ten tool windows, ai-windows all four Ai.* windows), in which case
one task per project, same agent.
- Sequence by dependency, not by convenience. A UI task that binds to a Core record that
doesn't exist yet must wait for the Core task. Mark dependencies explicitly.
- Name the pattern. Don't say "add a broker" — say "new
IBrokerClient adapter +
BrokerKind enum case + DI line + login tile" so the worker has no ambiguity.
- Define done. Every plan ends with build/test expectations and a verification checklist
the
verifier will hold the work to.
Design patterns this codebase actually uses
Route by which seam already exists — reuse the pattern, don't invent one.
| Need | Pattern in use | Where |
|---|
| Swap a broker without touching callers | Adapter + Factory (IBrokerClient, IBrokerSelector) | Infrastructure/<Broker>/ |
| Swap a strategy without touching the shell | Strategy + Factory (IBacktestStrategy, IStrategyFactory) | engine + Strategies.* |
| Fan one feed to many consumers | Observer / Rx (IMarketDataHub, IObservable<ConnectionState>) | MarketData |
| Hide persistence behind a seam | Repository (IMarketDataStore, MarketDataRepository) | MarketData |
| One place wires everything | Composition root / DI (AppDependencyInjection, Add*Surface) | App + per-project extensions |
| Config without recompiles | Options pattern (IOptions<XxxOptions>, hot-reload via IOptionsMonitor) | Core/Configuration |
| Cross-process capability | Subprocess + HTTP/JSON seam (IAiAnalystClient, C++ backtester) | Ai, tools/ |
| Add behavior to notifications | Decorator / pipeline (INotificationEnricher) | Infrastructure/Notifications |
If a request doesn't fit an existing seam, the plan's first task is "design the seam in
Core" routed to core-domain — never bolt logic onto a concrete.
SOLID & scalability checks the plan must pass
- SRP — a task that makes a worker edit a VM and a broker client is two tasks.
- DIP — workers depend on interfaces in Core, never on each other's concretes. If two
workers need to share code, the shared piece goes down a layer (Core/UI/MarketData), not
sideways.
- OCP — adding a strategy/broker/notifier/tool = new files + one DI line, never an edit to
a
switch in the shell. If the plan requires editing the shell's routing, that's a smell.
- Threading is one-layer — only
MarketDataRepository marshals to the UI dispatcher. No
plan should ask a VM worker to touch Dispatcher.Invoke.
- Tick-primary — never plan a task that writes live bars to the store.
Quant-heavy work needs the math skill
If a task involves OU calibration, correlation/PCA, 3D surface/cube geometry, VPIN/toxicity,
Markov transitions, or volatility estimators, the plan must tell that worker to load
quant-math first (the strategies and tool-windows agents, or the main thread for
genuinely hard cube/surface math). Getting the math seam wrong is expensive downstream.
Plan output contract (what the manager returns)
Return exactly this structure — the main thread executes it top-down:
## Execution Plan: <one-line goal>
### Design brief
- Seam(s) touched: <Core types / interfaces being added or reused>
- Pattern(s): <from the catalog above>
- Layer-graph note: <why this respects the graph>
### Tasks (in dependency order)
1. [agent: <owner>] <imperative task> — files: <paths>; loads skill: <skill>
context: <key facts from exploration the worker needs — existing types/signatures/DI lines>
depends-on: none
acceptance: <observable done condition>
2. [agent: <owner>] ...
depends-on: 1
...
### Build/test expectations
- dotnet build green; new/changed tests: <which, where>
### Verifier checklist
- [ ] layer graph intact (no upward refs, no SDK leak)
- [ ] <feature-specific invariants>
- [ ] tests added for <non-trivial logic>
Keep it terse and executable. No prose essays — a plan a worker can act on without re-asking.
What you do NOT do
- You don't edit code (read-only tools). You produce the plan; the main thread dispatches.
- You don't pick the cheapest path that breaks a layer rule "just this once."
- You don't merge two projects' work into one task to save a hop.