MicroFish/.kiro/steering/structure.md

167 lines
6.8 KiB
Markdown

# Project Structure
## Organization Philosophy
A **monorepo split by runtime** (`backend/` Python, `frontend/` Vue),
with each side organized **by layer**:
- Backend: `api/` (HTTP) → `services/` (logic) → `models/` (state) →
`utils/` (cross-cutting helpers), with `config.py` as the single source
of configuration.
- Frontend: `views/` (route-level pages) → `components/` (reusable UI) →
`api/` (HTTP services) → `store/`, `router/`, `i18n/`, `assets/`.
The core workflow is **pipeline-shaped** (5 sequential steps), and the
codebase mirrors that: each step has a backend service or service group,
a Flask blueprint endpoint, a frontend Step component, and (where useful)
a route-level view.
## Directory Patterns
### Backend HTTP Layer
**Location**: `backend/app/api/`
**Purpose**: One Flask blueprint per pipeline domain — thin handlers
that validate input, dispatch to services, and return JSON. No business
logic.
**Files**: `graph.py` (`graph_bp`), `simulation.py` (`simulation_bp`),
`report.py` (`report_bp`).
### Backend Services
**Location**: `backend/app/services/`
**Purpose**: All business logic. Each file owns one responsibility
(graph build, profile generation, simulation runner, report agent, etc.).
**Pattern**: Long-running operations expose an async/background entrypoint
that returns a `Task` and runs work off the request thread. Direct calls
to Neo4j, OASIS subprocesses, or LLM streaming live here, not in `api/`.
**Naming note**: Files prefixed `zep_*` are legacy from the Zep→Graphiti
migration. Don't rename casually (imports across the project), and don't
add new `zep_*` files.
### Backend State Models
**Location**: `backend/app/models/`
**Purpose**: In-memory, JSON-serializable state objects. `Project`
tracks per-project pipeline state and `group_id`; `Task` tracks
background-job status, progress, and result. These are the polling
contract with the frontend — change their shape with care.
### Backend Utilities
**Location**: `backend/app/utils/`
**Purpose**: Cross-cutting helpers usable from any service —
LLM client wrapper (`llm_client.py`), file parsing (`file_parser.py`),
retry (`retry.py`), logging (`logger.py`), locale (`locale.py`),
pagination helpers (`zep_paging.py`).
**Rule**: Utils never import from `services/` or `api/`.
### Backend Config
**Location**: `backend/app/config.py`
**Purpose**: Single file for LLM, Neo4j, embedding, chunking, OASIS,
and ReportAgent parameters. Read env vars here; consume the resulting
constants elsewhere. Avoid `os.getenv` calls scattered through services.
### Frontend Views (Routes)
**Location**: `frontend/src/views/`
**Purpose**: Page-level components mapped to routes (`Home.vue`,
`MainView.vue`, `Process.vue`, `SimulationView.vue`,
`SimulationRunView.vue`, `InteractionView.vue`, `ReportView.vue`).
**Pattern**: `Process.vue` is the workflow orchestrator (~50KB); it
composes the Step components and owns step transitions.
### Frontend Components
**Location**: `frontend/src/components/`
**Purpose**: Reusable UI. Step components (`Step1GraphBuild.vue`,
`Step2EnvSetup.vue`, `Step3Simulation.vue`, `Step4Report.vue`,
`Step5Interaction.vue`) implement one pipeline stage each;
`GraphPanel.vue` renders the D3 knowledge graph;
`HistoryDatabase.vue`, `LanguageSwitcher.vue` are general-purpose.
### Frontend API Services
**Location**: `frontend/src/api/`
**Purpose**: Axios services that wrap the backend blueprints —
`graph.js`, `simulation.js`, `report.js`, with `index.js` as the shared
client (5-min timeout, exponential retry).
**Rule**: Components and views call these services; they do not import
`axios` directly. New endpoints add a method on the matching service.
### Locales (shared)
**Location**: `/locales/` at repo root
**Purpose**: i18n source for both frontend (`vue-i18n`) and backend
(logger). Vite aliases `@locales` to this folder. Files: `en.json`,
`zh.json`, `languages.json`.
### Static Assets
**Location**: `static/` at repo root
**Purpose**: Images and demo assets referenced from READMEs (logos,
screenshots, video covers). Not bundled by Vite.
## Naming Conventions
- **Python files / modules / functions / vars**: `snake_case`
- **Python classes**: `PascalCase`
- **Python constants**: `UPPER_SNAKE_CASE`
- **Vue Single-File Components**: `PascalCase.vue`
- **Vue route views**: `<Name>View.vue` or domain noun
(`Home.vue`, `Process.vue`, `MainView.vue`)
- **Vue step components**: `Step<N><Name>.vue` (matches the pipeline stage)
- **Frontend non-component JS**: `camelCase.js` (e.g.
`pendingUpload.js`)
- **Locale files**: lowercase ISO code (`en.json`, `zh.json`) +
`languages.json` for the language list
- **Booleans (Python and JS)**: prefix with `is_` / `has_` / `should_`
where it improves clarity, but match local style first
## Import Organization
### Frontend (`frontend/src/`)
```js
// Vendor
import { ref, computed } from 'vue'
import axios from 'axios'
// Absolute (via @ alias)
import GraphPanel from '@/components/GraphPanel.vue'
import { fetchGraph } from '@/api/graph'
// Locales (shared with backend)
import en from '@locales/en.json'
// Relative (same feature only)
import { useStep } from './useStep'
```
**Path aliases** (`vite.config.js`):
- `@/``frontend/src/`
- `@locales` → repo-root `/locales/`
### Backend (`backend/app/`)
- Use absolute package imports (`from app.services.graph_builder import ...`).
- Layer dependency rule: `api → services → models / utils`. Services
may import from `models` and `utils`; `models` and `utils` never
import from `services` or `api`.
- All Neo4j/Graphiti access goes through `services/graphiti_adapter.py`.
## Code Organization Principles
- **Pipeline-aligned modules.** When adding a new pipeline-touching
feature, place code in the same backend service group and the same
frontend Step component as the stage it belongs to. Don't split a
stage across multiple services unless responsibilities genuinely
diverge.
- **Background tasks are uniform.** Any operation taking more than a
few seconds returns a `Task` and is polled. Don't introduce ad-hoc
status fields on `Project`; extend `Task`.
- **Per-project isolation.** Every graph operation must filter by
`group_id`. Cross-project reads are out of scope and should be
flagged in review.
- **IPC has one door.** Subprocess communication for the simulator goes
through `services/simulation_ipc.py`. Do not call `subprocess` /
pipe primitives elsewhere.
- **Configuration is centralized.** New tunables go in
`backend/app/config.py` (and an `.env.example` line if env-driven),
not as constants scattered through services.
- **Legacy filenames stay.** `zep_*` files predate the Graphiti
migration; leave the names alone to avoid touching every importer,
but don't add new `zep_*` files.
---
_Document patterns, not file trees. New files following patterns shouldn't require updates_