ai-ops-cli 0.1.8 → 0.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -1
- package/data/presets.yaml +56 -0
- package/data/rules/ai-llm-python.yaml +35 -0
- package/data/rules/code-philosophy.yaml +30 -0
- package/data/rules/communication.yaml +11 -0
- package/data/rules/data-pipeline-python.yaml +34 -0
- package/data/rules/engineering-standards.yaml +39 -0
- package/data/rules/fastapi.yaml +34 -0
- package/data/rules/flutter.yaml +40 -0
- package/data/rules/graphql.yaml +34 -0
- package/data/rules/libs-backend-python.yaml +35 -0
- package/data/rules/libs-backend-ts.yaml +38 -0
- package/data/rules/libs-frontend-app.yaml +39 -0
- package/data/rules/libs-frontend-web.yaml +44 -0
- package/data/rules/naming-convention.yaml +10 -0
- package/data/rules/nestjs-graphql.yaml +31 -0
- package/data/rules/nestjs.yaml +26 -0
- package/data/rules/nextjs.yaml +34 -0
- package/data/rules/plan-mode.yaml +30 -0
- package/data/rules/prisma-postgresql.yaml +30 -0
- package/data/rules/python.yaml +31 -0
- package/data/rules/react-typescript.yaml +11 -0
- package/data/rules/role-persona.yaml +14 -0
- package/data/rules/shadcn-ui.yaml +36 -0
- package/data/rules/sqlalchemy.yaml +32 -0
- package/data/rules/typescript.yaml +22 -0
- package/dist/bin/index.js +499 -119
- package/dist/bin/index.js.map +1 -1
- package/package.json +6 -3
package/README.md
CHANGED
|
@@ -2,6 +2,56 @@
|
|
|
2
2
|
|
|
3
3
|
CLI for managing AI tool rules and presets across projects.
|
|
4
4
|
|
|
5
|
+
## Why this exists
|
|
6
|
+
|
|
7
|
+
`ai-ops-cli` was created to reduce configuration drift across AI coding tools in a team.
|
|
8
|
+
|
|
9
|
+
- Different tools (Claude Code, Codex, Gemini CLI) require different file locations and prompt layouts.
|
|
10
|
+
- Tool conventions evolve over time, so manually maintained setup files become inconsistent quickly.
|
|
11
|
+
- Teams need a single, repeatable way to install and maintain AI rule scaffolding.
|
|
12
|
+
|
|
13
|
+
This project uses a centralized rule source (SSOT) and scaffolds tool-native files into the current project.
|
|
14
|
+
For the full product background and architecture intent, see [`docs/plan.md`](../../docs/plan.md).
|
|
15
|
+
|
|
16
|
+
### What this library provides
|
|
17
|
+
|
|
18
|
+
- Interactive installation flow for supported AI tools (`ai-ops init`)
|
|
19
|
+
- Managed updates based on installed manifest (`ai-ops update`)
|
|
20
|
+
- Drift detection against current source hash (`ai-ops diff`)
|
|
21
|
+
- Safe cleanup of installed managed files + manifest (`ai-ops uninstall`)
|
|
22
|
+
- Project-local installation and management
|
|
23
|
+
|
|
24
|
+
### What this library does not provide
|
|
25
|
+
|
|
26
|
+
- A hosted backend or remote state service
|
|
27
|
+
- Rule authoring workflow inside the CLI itself
|
|
28
|
+
- IDE-specific plugin management
|
|
29
|
+
|
|
30
|
+
## Supported AI tools and installation model
|
|
31
|
+
|
|
32
|
+
`ai-ops-cli` currently supports:
|
|
33
|
+
|
|
34
|
+
- Claude Code (`claude-code`)
|
|
35
|
+
- Codex (`codex`)
|
|
36
|
+
- Gemini CLI (`gemini`)
|
|
37
|
+
|
|
38
|
+
### Tool-specific installation layout
|
|
39
|
+
|
|
40
|
+
| Tool | Single project | Monorepo | Why this layout (JIT rationale) |
|
|
41
|
+
| ----------- | ------------------------------------- | ----------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
|
|
42
|
+
| Claude Code | `.claude/rules/<rule-id>.md` per rule | Shared rules in `.claude/rules/*.md`, domain rules in `<workspace>/CLAUDE.md` | Keeps always-on rules stable while loading domain rules only for matching paths/workspaces. |
|
|
43
|
+
| Codex | `AGENTS.md` + `AGENTS.override.md` | Root `AGENTS.md` + `<workspace>/AGENTS.override.md` | Uses root baseline + local override so only relevant workspace context is applied at execution time. |
|
|
44
|
+
| Gemini CLI | `.gemini/GEMINI.md` | Root `.gemini/GEMINI.md` + `<workspace>/GEMINI.md` | Splits shared defaults and workspace-local context to reduce irrelevant prompt context. |
|
|
45
|
+
|
|
46
|
+
Gemini CLI can also install optional runtime settings to `.gemini/settings.json`.
|
|
47
|
+
|
|
48
|
+
### Installation behavior details
|
|
49
|
+
|
|
50
|
+
- Rules are split into shared and domain categories and rendered per tool with tool-native file shapes.
|
|
51
|
+
- Existing managed files are replaced safely using ai-ops metadata headers.
|
|
52
|
+
- Existing non-managed files are preserved and receive an `ai-ops` managed section block instead of full overwrite.
|
|
53
|
+
- `update`, `diff`, and `uninstall` operate from the manifest to keep changes deterministic and idempotent.
|
|
54
|
+
|
|
5
55
|
## Install
|
|
6
56
|
|
|
7
57
|
```bash
|
|
@@ -19,6 +69,9 @@ ai-ops diff
|
|
|
19
69
|
|
|
20
70
|
# Apply updates
|
|
21
71
|
ai-ops update
|
|
72
|
+
|
|
73
|
+
# Remove installed managed files and manifest
|
|
74
|
+
ai-ops uninstall
|
|
22
75
|
```
|
|
23
76
|
|
|
24
77
|
## Options
|
|
@@ -30,9 +83,9 @@ Commands:
|
|
|
30
83
|
init Initialize AI tool rules for a project
|
|
31
84
|
update Update installed rules
|
|
32
85
|
diff Show diff between installed and current rules
|
|
86
|
+
uninstall Remove installed rules and manifest
|
|
33
87
|
|
|
34
88
|
Options:
|
|
35
|
-
--scope <scope> Target scope: project (default) or global
|
|
36
89
|
--force Force update even when no changes detected
|
|
37
90
|
-V, --version Output the version number
|
|
38
91
|
-h, --help Display help
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
frontend-web:
|
|
2
|
+
description: '웹 프론트엔드 프로젝트를 위한 프리셋'
|
|
3
|
+
rules:
|
|
4
|
+
- role-persona
|
|
5
|
+
- communication
|
|
6
|
+
- code-philosophy
|
|
7
|
+
- plan-mode
|
|
8
|
+
- naming-convention
|
|
9
|
+
- engineering-standards
|
|
10
|
+
- typescript
|
|
11
|
+
- react-typescript
|
|
12
|
+
- shadcn-ui
|
|
13
|
+
- nextjs
|
|
14
|
+
- libs-frontend-web
|
|
15
|
+
|
|
16
|
+
frontend-app:
|
|
17
|
+
description: '앱 프론트엔드 프로젝트를 위한 프리셋'
|
|
18
|
+
rules:
|
|
19
|
+
- role-persona
|
|
20
|
+
- communication
|
|
21
|
+
- code-philosophy
|
|
22
|
+
- plan-mode
|
|
23
|
+
- naming-convention
|
|
24
|
+
- engineering-standards
|
|
25
|
+
- flutter
|
|
26
|
+
- libs-frontend-app
|
|
27
|
+
|
|
28
|
+
backend-ts:
|
|
29
|
+
description: 'TypeScript 백엔드 프로젝트를 위한 프리셋'
|
|
30
|
+
rules:
|
|
31
|
+
- role-persona
|
|
32
|
+
- communication
|
|
33
|
+
- code-philosophy
|
|
34
|
+
- plan-mode
|
|
35
|
+
- naming-convention
|
|
36
|
+
- engineering-standards
|
|
37
|
+
- typescript
|
|
38
|
+
- nestjs
|
|
39
|
+
- prisma-postgresql
|
|
40
|
+
- graphql
|
|
41
|
+
- nestjs-graphql
|
|
42
|
+
- libs-backend-ts
|
|
43
|
+
|
|
44
|
+
backend-python:
|
|
45
|
+
description: 'Python 백엔드 프로젝트를 위한 프리셋'
|
|
46
|
+
rules:
|
|
47
|
+
- role-persona
|
|
48
|
+
- communication
|
|
49
|
+
- code-philosophy
|
|
50
|
+
- plan-mode
|
|
51
|
+
- naming-convention
|
|
52
|
+
- engineering-standards
|
|
53
|
+
- python
|
|
54
|
+
- fastapi
|
|
55
|
+
- sqlalchemy
|
|
56
|
+
- libs-backend-python
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
id: ai-llm-python
|
|
2
|
+
category: domain
|
|
3
|
+
tags:
|
|
4
|
+
- python
|
|
5
|
+
- llm
|
|
6
|
+
- ai
|
|
7
|
+
priority: 28
|
|
8
|
+
content:
|
|
9
|
+
constraints:
|
|
10
|
+
- 'DO NOT parse model outputs with regex/split when schema output is required. Use structured output (Pydantic + response_format/function calling/instructor).'
|
|
11
|
+
- 'DO NOT hardcode prompts inline. Keep prompts versioned in files or managed storage.'
|
|
12
|
+
- 'DO NOT call sync SDK methods from async app paths.'
|
|
13
|
+
- 'DO NOT ignore token limits. Estimate and chunk/truncate input before requests.'
|
|
14
|
+
- 'DO NOT log raw responses containing PII.'
|
|
15
|
+
guidelines:
|
|
16
|
+
- 'Use Pydantic models with instructor or native response_format JSON schema mode.'
|
|
17
|
+
- 'Apply retry with exponential backoff for 429/5xx transient errors.'
|
|
18
|
+
- 'Centralize provider routing via LiteLLM (or equivalent abstraction).'
|
|
19
|
+
- 'Track model, input/output tokens, and latency per call for cost/perf monitoring.'
|
|
20
|
+
- 'Version prompts and include prompt version in request logs.'
|
|
21
|
+
- 'Stream user-facing responses when possible; keep non-streaming for strict structured extraction flows.'
|
|
22
|
+
- 'Define fallback model chains for rate limits or provider outages.'
|
|
23
|
+
decision_table:
|
|
24
|
+
- when: 'Output must match a strict schema'
|
|
25
|
+
then: 'Use structured output with Pydantic schema validation'
|
|
26
|
+
avoid: 'Regex parsing on free-text responses'
|
|
27
|
+
- when: 'Selecting a model'
|
|
28
|
+
then: 'Use the smallest model that meets quality requirements'
|
|
29
|
+
avoid: 'Defaulting to the largest model for all tasks'
|
|
30
|
+
- when: 'Input exceeds context window'
|
|
31
|
+
then: 'Chunk with overlap and aggregate results'
|
|
32
|
+
avoid: 'Silent SDK truncation'
|
|
33
|
+
- when: 'Multiple providers are required'
|
|
34
|
+
then: 'Use a unified provider abstraction (e.g., LiteLLM)'
|
|
35
|
+
avoid: 'Scattered provider-specific call sites'
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
id: code-philosophy
|
|
2
|
+
category: philosophy
|
|
3
|
+
tags:
|
|
4
|
+
- general
|
|
5
|
+
- philosophy
|
|
6
|
+
- tdd
|
|
7
|
+
- functional
|
|
8
|
+
- immutability
|
|
9
|
+
priority: 80
|
|
10
|
+
content:
|
|
11
|
+
constraints:
|
|
12
|
+
- 'DO NOT write clever or opaque code. Prefer explicit intent over tricks.'
|
|
13
|
+
- 'DO NOT extract shared abstractions before the Rule of Three.'
|
|
14
|
+
- 'DO NOT mutate state. Use const/final and spread operators for immutability.'
|
|
15
|
+
- 'DO NOT mix side effects into core business functions.'
|
|
16
|
+
guidelines:
|
|
17
|
+
- 'Optimize for readability and maintainability first.'
|
|
18
|
+
- 'Prefer temporary duplication over premature abstraction.'
|
|
19
|
+
- 'For non-trivial business rules, start with a failing test (TDD).'
|
|
20
|
+
- 'Use a functional-core / imperative-shell structure.'
|
|
21
|
+
- 'Use immutable updates (const/final, copy/spread patterns).'
|
|
22
|
+
decision_table:
|
|
23
|
+
- when: 'Implementing complex business logic'
|
|
24
|
+
then: 'Write failing tests first, then implement pure functions'
|
|
25
|
+
avoid: 'Implementation-first with mixed I/O'
|
|
26
|
+
- when: 'Similar code appears in two places'
|
|
27
|
+
then: 'Keep duplication temporarily'
|
|
28
|
+
avoid: 'Early shared abstraction'
|
|
29
|
+
- when: 'Similar code appears in three or more places'
|
|
30
|
+
then: 'Extract a clearly named shared function'
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
id: communication
|
|
2
|
+
category: communication
|
|
3
|
+
tags:
|
|
4
|
+
- general
|
|
5
|
+
- communication
|
|
6
|
+
priority: 85
|
|
7
|
+
content:
|
|
8
|
+
constraints:
|
|
9
|
+
- "DO NOT use filler phrases like 'Certainly,' 'Of course,' 'Here is the code,' 'I understand,' 'Great question.' Just output the solution."
|
|
10
|
+
guidelines:
|
|
11
|
+
- 'Think and explain in Korean. Write code and comments in English.'
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
id: data-pipeline-python
|
|
2
|
+
category: domain
|
|
3
|
+
tags:
|
|
4
|
+
- python
|
|
5
|
+
- data-engineering
|
|
6
|
+
- polars
|
|
7
|
+
- duckdb
|
|
8
|
+
priority: 33
|
|
9
|
+
content:
|
|
10
|
+
constraints:
|
|
11
|
+
- 'DO NOT iterate DataFrame rows in Python loops for transformations.'
|
|
12
|
+
- 'DO NOT use Pandas .apply(axis=1). It runs at Python speed; use vectorized expressions or Polars.'
|
|
13
|
+
- 'DO NOT load datasets larger than memory in one shot.'
|
|
14
|
+
- 'DO NOT rely on implicit dtype inference for production pipelines.'
|
|
15
|
+
- 'DO NOT mutate DataFrames in-place.'
|
|
16
|
+
guidelines:
|
|
17
|
+
- 'Prefer Polars for new pipelines, especially lazy mode for query pushdown and parallel execution.'
|
|
18
|
+
- 'Use DuckDB for local SQL analytics on Parquet/CSV and out-of-core workloads.'
|
|
19
|
+
- 'Use streaming/chunked reads for large sources (scan_*, batched readers, out-of-core SQL).'
|
|
20
|
+
- 'Write partitioned Parquet outputs for downstream pruning and faster reads.'
|
|
21
|
+
- 'Enforce explicit schemas at I/O boundaries.'
|
|
22
|
+
decision_table:
|
|
23
|
+
- when: 'Transforming tables up to medium-large scale'
|
|
24
|
+
then: 'Use Polars lazy pipelines'
|
|
25
|
+
avoid: 'Row-wise pandas patterns'
|
|
26
|
+
- when: 'Ad-hoc SQL analysis on local files is needed'
|
|
27
|
+
then: 'Use DuckDB directly on source files'
|
|
28
|
+
avoid: 'Load-all-then-filter in pandas'
|
|
29
|
+
- when: 'Data exceeds available memory'
|
|
30
|
+
then: 'Use Polars scan_* or DuckDB out-of-core execution'
|
|
31
|
+
avoid: 'Full-memory pandas reads'
|
|
32
|
+
- when: 'Custom per-row Python logic is unavoidable'
|
|
33
|
+
then: 'Use vectorized expressions or controlled map APIs'
|
|
34
|
+
avoid: 'General-purpose iter_rows for core pipelines'
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
id: engineering-standards
|
|
2
|
+
category: standard
|
|
3
|
+
tags:
|
|
4
|
+
- general
|
|
5
|
+
- api
|
|
6
|
+
- data-format
|
|
7
|
+
- cross-cutting
|
|
8
|
+
priority: 70
|
|
9
|
+
content:
|
|
10
|
+
constraints:
|
|
11
|
+
- 'DO NOT use floating-point for money. Use minor-unit integers with ISO 4217 currency (e.g., { amount: 1099, currency: "USD" }).'
|
|
12
|
+
- 'DO NOT expose sequential IDs in external APIs. Use UUIDs (prefer UUID v7).'
|
|
13
|
+
- 'DO NOT store or transmit timezone-naive timestamps. Use ISO 8601 UTC (e.g., "2024-01-15T09:30:00Z").'
|
|
14
|
+
- 'DO NOT use magic numbers or strings inline. Extract constants or config.'
|
|
15
|
+
- 'DO NOT return inconsistent error shapes. Use { code: string, message: string, details?: unknown[] }.'
|
|
16
|
+
- 'DO NOT accept unbounded input. Enforce body, array, and string size limits at the API boundary.'
|
|
17
|
+
guidelines:
|
|
18
|
+
- 'Use UTC end-to-end: TIMESTAMPTZ in DB, ISO 8601 UTC in API/logs, local conversion only in the presentation layer.'
|
|
19
|
+
- 'Wrap API responses in a consistent envelope: { data: T | null, error: ErrorEnvelope | null, meta: { requestId: string, timestamp: string } }.'
|
|
20
|
+
- 'Propagate X-Request-Id across gateway, service, logs, DB comments, and outbound calls.'
|
|
21
|
+
- 'Validate environment variables at startup (e.g., Zod parse) and fail fast with all missing/invalid keys.'
|
|
22
|
+
- 'Use domain error codes in DOMAIN_ACTION_REASON format (e.g., PAYMENT_CHARGE_INSUFFICIENT_FUNDS).'
|
|
23
|
+
- 'Support Idempotency-Key for POST/PATCH and replay the cached response for duplicate keys within TTL.'
|
|
24
|
+
- 'Expose GET /health (liveness) and GET /ready (readiness) separately.'
|
|
25
|
+
- 'Return empty collections ([] or {}) instead of null.'
|
|
26
|
+
- 'Handle SIGTERM gracefully: stop intake, drain in-flight requests, close resources, then exit.'
|
|
27
|
+
decision_table:
|
|
28
|
+
- when: 'A new entity needs a primary key'
|
|
29
|
+
then: 'Use UUID v7'
|
|
30
|
+
avoid: 'Auto-increment IDs or UUID v4 by default'
|
|
31
|
+
- when: 'An endpoint returns an error'
|
|
32
|
+
then: 'Return the standard error envelope'
|
|
33
|
+
avoid: 'Ad-hoc error fields (e.g., { success: false, msg })'
|
|
34
|
+
- when: 'Systems exchange timestamps'
|
|
35
|
+
then: 'Use ISO 8601 UTC in API/logs and TIMESTAMPTZ in DB; Unix epoch is acceptable in compact token formats (e.g., JWT exp/iat)'
|
|
36
|
+
avoid: 'Timezone-naive strings or mixed local-time storage'
|
|
37
|
+
- when: 'An API needs versioning'
|
|
38
|
+
then: 'Use URL versioning (/v1, /v2)'
|
|
39
|
+
avoid: 'Header-only versioning by default'
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
id: fastapi
|
|
2
|
+
category: framework
|
|
3
|
+
tags:
|
|
4
|
+
- python
|
|
5
|
+
- fastapi
|
|
6
|
+
- backend
|
|
7
|
+
priority: 42
|
|
8
|
+
content:
|
|
9
|
+
constraints:
|
|
10
|
+
- 'DO NOT use plain dict/TypedDict as request or response models. Use Pydantic BaseModel with Field constraints.'
|
|
11
|
+
- 'DO NOT run blocking I/O in async handlers. Use async clients or offload to executors.'
|
|
12
|
+
- 'DO NOT return ad-hoc error dicts from handlers. Raise HTTPException/custom exceptions and centralize handlers.'
|
|
13
|
+
- 'DO NOT place business logic in routers. Keep routers thin and inject services via Depends().'
|
|
14
|
+
- 'DO NOT hardcode CORS origins. Load from validated settings.'
|
|
15
|
+
guidelines:
|
|
16
|
+
- 'Use reusable Depends() providers for DB session, auth context, and services.'
|
|
17
|
+
- 'Use APIRouter per domain with clear prefixes/tags and mount in the main app.'
|
|
18
|
+
- 'Set response_model on endpoints for output filtering and OpenAPI correctness.'
|
|
19
|
+
- 'Use Annotated[T, Depends(...)] for typed dependency injection.'
|
|
20
|
+
- 'Use Pydantic Settings for startup-time environment validation.'
|
|
21
|
+
- 'Use lifespan context manager for startup/shutdown lifecycle management.'
|
|
22
|
+
decision_table:
|
|
23
|
+
- when: 'Endpoint is CPU-bound'
|
|
24
|
+
then: 'Use sync def and let FastAPI run it in the threadpool'
|
|
25
|
+
avoid: 'async def with blocking code'
|
|
26
|
+
- when: 'Endpoint is I/O-bound'
|
|
27
|
+
then: 'Use async def with async drivers (asyncpg, httpx, aiofiles)'
|
|
28
|
+
avoid: 'Sync driver calls on hot paths'
|
|
29
|
+
- when: 'Shared resources need setup/teardown'
|
|
30
|
+
then: 'Use lifespan async context manager'
|
|
31
|
+
avoid: '@app.on_event startup/shutdown hooks'
|
|
32
|
+
- when: 'Post-response background work is required'
|
|
33
|
+
then: 'Use BackgroundTasks for light jobs, Celery/TaskIQ for heavy/retriable jobs'
|
|
34
|
+
avoid: 'Awaiting long tasks inside the request handler'
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
id: flutter
|
|
2
|
+
category: framework
|
|
3
|
+
tags:
|
|
4
|
+
- dart
|
|
5
|
+
- flutter
|
|
6
|
+
- riverpod
|
|
7
|
+
- mobile
|
|
8
|
+
priority: 30
|
|
9
|
+
content:
|
|
10
|
+
constraints:
|
|
11
|
+
- 'DO NOT use dynamic as a default type. Prefer concrete types, Object, or sealed unions.'
|
|
12
|
+
- 'DO NOT put business logic in Widget build(). Keep widgets declarative.'
|
|
13
|
+
- 'DO NOT use StatefulWidget for shared or long-lived state. Use Riverpod providers.'
|
|
14
|
+
- 'DO NOT use GlobalKey to reach into child state for app data flow.'
|
|
15
|
+
- 'DO NOT keep mutable model fields. Prefer immutable classes with copyWith/freezed.'
|
|
16
|
+
- 'DO NOT run heavy synchronous work on the UI thread. Use compute or Isolate.'
|
|
17
|
+
guidelines:
|
|
18
|
+
- 'Use Riverpod with @riverpod code generation and feature-local providers.'
|
|
19
|
+
- 'Use feature-first directories: lib/features/<feature>/{view,model,provider,logic} and shared code in lib/core.'
|
|
20
|
+
- 'Use sealed classes and pattern matching for Result/Async state handling.'
|
|
21
|
+
- 'Prefer const constructors where possible for rebuild efficiency.'
|
|
22
|
+
- 'Use go_router for declarative routes and deep-link handling.'
|
|
23
|
+
- 'Use freezed for immutable models and generated equality/copy/JSON methods.'
|
|
24
|
+
- 'Write widget tests with ProviderScope.overrides and unit-test pure logic separately.'
|
|
25
|
+
- 'Profile with DevTools before optimization; use RepaintBoundary where repaint isolation is needed.'
|
|
26
|
+
- 'Handle async states explicitly with AsyncValue or a Result type (loading/success/failure). Set a global error boundary to catch unhandled exceptions before they reach the UI.'
|
|
27
|
+
- 'Access external APIs/storage via repositories; providers should depend on repository interfaces.'
|
|
28
|
+
decision_table:
|
|
29
|
+
- when: 'State is local and ephemeral (focus, small toggle)'
|
|
30
|
+
then: 'Use StatefulWidget or flutter_hooks state'
|
|
31
|
+
avoid: 'Creating global/shared providers for trivial local state'
|
|
32
|
+
- when: 'State is shared or must outlive a widget'
|
|
33
|
+
then: 'Use Riverpod Notifier/AsyncNotifier'
|
|
34
|
+
avoid: 'Prop-drilling callback chains'
|
|
35
|
+
- when: 'A model needs equality/copy/JSON generation'
|
|
36
|
+
then: 'Use @freezed + build_runner'
|
|
37
|
+
avoid: 'Manual ==/hashCode/copyWith implementations'
|
|
38
|
+
- when: 'Navigation and deep links are needed'
|
|
39
|
+
then: 'Use GoRouter route configuration'
|
|
40
|
+
avoid: 'Imperative Navigator-only architecture'
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
id: graphql
|
|
2
|
+
category: api
|
|
3
|
+
tags:
|
|
4
|
+
- graphql
|
|
5
|
+
- api
|
|
6
|
+
- schema-design
|
|
7
|
+
priority: 48
|
|
8
|
+
content:
|
|
9
|
+
constraints:
|
|
10
|
+
- 'DO NOT rely on implicit nullability. Mark every field intentionally (prefer non-null by default).'
|
|
11
|
+
- 'DO NOT perform mutations in Query resolvers. Reads belong to Query, writes belong to Mutation.'
|
|
12
|
+
- 'DO NOT return a generic Error type. Use operation-specific typed errors (union or payload errors).'
|
|
13
|
+
- 'DO NOT return unbounded lists. Every collection must support pagination.'
|
|
14
|
+
- 'DO NOT expose internal implementation details in enum values. Use semantic SCREAMING_SNAKE_CASE names.'
|
|
15
|
+
guidelines:
|
|
16
|
+
- 'Prefer cursor pagination (first/after) for user-facing lists; use offset pagination only for bounded admin tables.'
|
|
17
|
+
- 'Use a single input object for every mutation: mutation X($input: XInput!).'
|
|
18
|
+
- 'Return mutation payload types that can carry both result data and structured errors.'
|
|
19
|
+
- 'Use DataLoader for related entity resolution; field resolvers must not issue per-parent DB queries.'
|
|
20
|
+
- 'Follow naming conventions: PascalCase types/enums, camelCase fields/args, SCREAMING_SNAKE_CASE enum values.'
|
|
21
|
+
- 'Deprecate fields first with @deprecated(reason: "...") and remove only in the next major version.'
|
|
22
|
+
decision_table:
|
|
23
|
+
- when: 'A field returns a collection'
|
|
24
|
+
then: 'Use cursor pagination with a stable cursor'
|
|
25
|
+
avoid: 'Returning unbounded [Node!]! lists'
|
|
26
|
+
- when: 'A mutation must report business failure'
|
|
27
|
+
then: 'Use both a Payload wrapper type AND typed union errors together — Payload carries partial success data, union enables __typename switching; they are complementary, not alternatives'
|
|
28
|
+
avoid: 'Throwing top-level GraphQL errors for expected failures, or using only a bare union without a Payload'
|
|
29
|
+
- when: 'A field is removed or renamed'
|
|
30
|
+
then: 'Deprecate first, migrate clients, then remove in next major'
|
|
31
|
+
avoid: 'Immediate schema removal'
|
|
32
|
+
- when: 'Filtering or sorting is complex'
|
|
33
|
+
then: 'Define typed FilterInput/OrderByInput types'
|
|
34
|
+
avoid: 'Accepting raw JSON or string filters'
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
id: libs-backend-python
|
|
2
|
+
category: tooling
|
|
3
|
+
tags:
|
|
4
|
+
- python
|
|
5
|
+
- backend
|
|
6
|
+
priority: 22
|
|
7
|
+
content:
|
|
8
|
+
constraints:
|
|
9
|
+
- 'DO NOT use requirements.txt as the primary dependency spec. Use pyproject.toml with uv (preferred) or Poetry, and commit the lock file.'
|
|
10
|
+
- 'DO NOT use print() for logging. Use structured JSON logging (structlog).'
|
|
11
|
+
- 'DO NOT use unittest.TestCase. Use pytest with fixtures.'
|
|
12
|
+
- 'DO NOT rely on bare assert in production code. Raise explicit exceptions.'
|
|
13
|
+
guidelines:
|
|
14
|
+
- 'Use uv for environment and dependency management (uv sync, uv run).'
|
|
15
|
+
- 'Use pytest + pytest-asyncio + pytest-cov for tests.'
|
|
16
|
+
- 'Use httpx for sync/async HTTP and ASGITransport for FastAPI integration tests.'
|
|
17
|
+
- 'Use structlog and bind request_id/user_id in context.'
|
|
18
|
+
- 'Use ruff for lint + format and enforce it in CI.'
|
|
19
|
+
- 'Use mypy or pyright in strict mode.'
|
|
20
|
+
- 'Use pydantic-settings for env loading/validation.'
|
|
21
|
+
- 'Use tenacity for retry/backoff around transient external calls.'
|
|
22
|
+
- 'Use pandera or Great Expectations for data quality validation in pipelines.'
|
|
23
|
+
decision_table:
|
|
24
|
+
- when: 'Package management is needed'
|
|
25
|
+
then: 'Use uv + pyproject.toml + lock file'
|
|
26
|
+
avoid: 'pip-only requirements.txt workflows'
|
|
27
|
+
- when: 'Lint/format tooling is needed'
|
|
28
|
+
then: 'Use ruff as the default toolchain'
|
|
29
|
+
avoid: 'Split flake8/black/isort stacks'
|
|
30
|
+
- when: 'Data quality checks are needed'
|
|
31
|
+
then: 'Use pandera or Great Expectations with explicit checks'
|
|
32
|
+
avoid: 'Scattered inline asserts with no reporting'
|
|
33
|
+
- when: 'HTTP client is needed'
|
|
34
|
+
then: 'Use httpx'
|
|
35
|
+
avoid: 'Mixing requests/aiohttp across services'
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
id: libs-backend-ts
|
|
2
|
+
category: tooling
|
|
3
|
+
tags:
|
|
4
|
+
- typescript
|
|
5
|
+
- nestjs
|
|
6
|
+
- backend
|
|
7
|
+
priority: 25
|
|
8
|
+
content:
|
|
9
|
+
constraints:
|
|
10
|
+
- 'DO NOT use moment/dayjs. Standardize on date-fns with named imports.'
|
|
11
|
+
- 'DO NOT use jsonwebtoken. Use jose 6+.'
|
|
12
|
+
- 'DO NOT handle Express req/res directly in NestJS handlers.'
|
|
13
|
+
- 'DO NOT import lodash as a full bundle. Prefer native APIs or per-function imports.'
|
|
14
|
+
- 'DO NOT use node-fetch/got in NestJS services. Use @nestjs/axios HttpModule or native fetch().'
|
|
15
|
+
- 'DO NOT use winston/morgan/console.log for app logs. Use pino via nestjs-pino.'
|
|
16
|
+
guidelines:
|
|
17
|
+
- 'Use class-validator + class-transformer DTO validation with ValidationPipe({ whitelist: true }).'
|
|
18
|
+
- 'Use @nestjs/graphql + @nestjs/apollo code-first for GraphQL APIs.'
|
|
19
|
+
- 'Use GraphQL Codegen for operation/result type generation.'
|
|
20
|
+
- 'Use jose for JWT sign/verify and JWKS workflows.'
|
|
21
|
+
- 'Use pino + nestjs-pino as the default structured logger.'
|
|
22
|
+
- 'Use rxjs operators for NestJS interceptors, guards, and event streams.'
|
|
23
|
+
- 'Use Vitest + @nestjs/testing + supertest for unit/e2e tests.'
|
|
24
|
+
- 'Use zod for schema validation outside DTOs (env, external payloads).'
|
|
25
|
+
- 'Keep TypeScript strict mode enabled.'
|
|
26
|
+
decision_table:
|
|
27
|
+
- when: 'JWT auth is needed'
|
|
28
|
+
then: 'Use jose (SignJWT, jwtVerify, createRemoteJWKSet)'
|
|
29
|
+
avoid: 'jsonwebtoken'
|
|
30
|
+
- when: 'Date handling is needed'
|
|
31
|
+
then: 'Use date-fns named imports'
|
|
32
|
+
avoid: 'moment/dayjs'
|
|
33
|
+
- when: 'Utility helpers are needed (clone/groupBy)'
|
|
34
|
+
then: 'Use native JS first; fallback to scoped lodash imports only'
|
|
35
|
+
avoid: 'import _ from "lodash"'
|
|
36
|
+
- when: 'Structured logging is needed'
|
|
37
|
+
then: 'Use pino via nestjs-pino LoggerModule.forRoot()'
|
|
38
|
+
avoid: 'console.log or mixed logging stacks'
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
id: libs-frontend-app
|
|
2
|
+
category: tooling
|
|
3
|
+
tags:
|
|
4
|
+
- dart
|
|
5
|
+
- flutter
|
|
6
|
+
- frontend
|
|
7
|
+
priority: 15
|
|
8
|
+
content:
|
|
9
|
+
constraints:
|
|
10
|
+
- 'DO NOT use http for API calls. Standardize on dio 5+.'
|
|
11
|
+
- 'DO NOT use Provider or Bloc. Standardize on flutter_riverpod with code generation.'
|
|
12
|
+
- 'DO NOT handwrite data classes (==, hashCode, copyWith, toJson). Use freezed.'
|
|
13
|
+
- 'DO NOT use Navigator 1.0 push/pop APIs for app routing. Use go_router.'
|
|
14
|
+
- 'DO NOT manually implement JSON serialization for models. Use json_serializable/freezed generation.'
|
|
15
|
+
guidelines:
|
|
16
|
+
- 'Use @riverpod with riverpod_generator and build_runner for provider generation.'
|
|
17
|
+
- 'Use freezed for immutable models and unions.'
|
|
18
|
+
- 'Define routes in a central GoRouter config and navigate with context.go()/push().'
|
|
19
|
+
- 'Create one shared Dio instance via Riverpod DI with interceptors and auth headers.'
|
|
20
|
+
- 'Use shared_preferences for non-sensitive keys and flutter_secure_storage for secrets.'
|
|
21
|
+
- 'Use cached_network_image for network image caching and placeholders.'
|
|
22
|
+
- 'Use very_good_analysis and treat warnings as CI failures.'
|
|
23
|
+
- 'Use intl/easy_localization with ARB-based translations.'
|
|
24
|
+
decision_table:
|
|
25
|
+
- when: 'HTTP API calls are needed'
|
|
26
|
+
then: 'Use DI-injected central Dio client'
|
|
27
|
+
avoid: 'Per-feature ad-hoc http clients'
|
|
28
|
+
- when: 'Simple local persistence is needed'
|
|
29
|
+
then: 'Use shared_preferences or flutter_secure_storage by data sensitivity'
|
|
30
|
+
avoid: 'SQLite/Hive for plain key-value settings'
|
|
31
|
+
- when: 'Network images are rendered'
|
|
32
|
+
then: 'Use cached_network_image with placeholder/error states'
|
|
33
|
+
avoid: 'Bare Image.network everywhere'
|
|
34
|
+
- when: 'Test mocking is needed'
|
|
35
|
+
then: 'Use mocktail (class-based, no code generation required)'
|
|
36
|
+
avoid: 'mockito with @GenerateMocks annotation boilerplate'
|
|
37
|
+
- when: 'Code generation is required'
|
|
38
|
+
then: 'Run build_runner watch in dev and build in CI'
|
|
39
|
+
avoid: 'Manually editing generated files'
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
id: libs-frontend-web
|
|
2
|
+
category: tooling
|
|
3
|
+
tags:
|
|
4
|
+
- typescript
|
|
5
|
+
- react
|
|
6
|
+
- nextjs
|
|
7
|
+
- frontend
|
|
8
|
+
priority: 20
|
|
9
|
+
content:
|
|
10
|
+
constraints:
|
|
11
|
+
- 'DO NOT use moment.js or dayjs. Standardize on date-fns with named imports.'
|
|
12
|
+
- 'DO NOT use react-icons. Use lucide-react named imports only.'
|
|
13
|
+
- 'DO NOT use axios in browser code. Use native fetch() for Next.js cache/revalidate integration.'
|
|
14
|
+
- 'DO NOT build conditional className strings manually. Use cn() and cva().'
|
|
15
|
+
- 'DO NOT install parallel UI kits (MUI, Ant, Chakra) alongside shadcn/ui.'
|
|
16
|
+
- 'DO NOT use Redux/Recoil/MobX for local UI state. Use zustand for client UI state.'
|
|
17
|
+
guidelines:
|
|
18
|
+
- 'Use @apollo/client with @apollo/experimental-nextjs-app-support for GraphQL in App Router.'
|
|
19
|
+
- 'Use GraphQL Codegen client-preset to generate TypedDocumentNode types at build time.'
|
|
20
|
+
- 'Keep styling on Tailwind + design tokens (CSS variables) and cva variants.'
|
|
21
|
+
- 'Use next-intl for i18n and next-themes for theme switching.'
|
|
22
|
+
- 'Render Recharts inside client components only.'
|
|
23
|
+
- 'Mount one Sonner <Toaster /> at the app root and call toast() from features.'
|
|
24
|
+
- 'Sanitize user HTML with isomorphic-dompurify before dangerouslySetInnerHTML.'
|
|
25
|
+
- 'Use Vitest + Testing Library; prefer userEvent over fireEvent.'
|
|
26
|
+
decision_table:
|
|
27
|
+
- when: 'GraphQL data fetching is needed in App Router'
|
|
28
|
+
then: 'Use ApolloNextAppProvider with @apollo/client'
|
|
29
|
+
avoid: 'Ad-hoc raw fetch cache wiring'
|
|
30
|
+
- when: 'Date handling is needed'
|
|
31
|
+
then: 'Use date-fns named imports'
|
|
32
|
+
avoid: 'moment/dayjs'
|
|
33
|
+
- when: 'Icons are needed'
|
|
34
|
+
then: 'Use lucide-react named imports'
|
|
35
|
+
avoid: 'react-icons or inline SVG'
|
|
36
|
+
- when: 'Form validation is needed'
|
|
37
|
+
then: 'Use zod + react-hook-form + zod resolver'
|
|
38
|
+
avoid: 'Manual validation in component event handlers'
|
|
39
|
+
- when: 'User-generated HTML must be rendered'
|
|
40
|
+
then: 'Sanitize with isomorphic-dompurify first, then dangerouslySetInnerHTML'
|
|
41
|
+
avoid: 'Rendering unsanitized HTML (XSS risk)'
|
|
42
|
+
- when: 'Client UI state is needed (modals, wizard step, sidebar)'
|
|
43
|
+
then: 'Use a zustand slice'
|
|
44
|
+
avoid: 'Global Redux/Recoil for simple UI state'
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
id: nestjs-graphql
|
|
2
|
+
category: framework
|
|
3
|
+
tags:
|
|
4
|
+
- typescript
|
|
5
|
+
- nestjs
|
|
6
|
+
- graphql
|
|
7
|
+
priority: 43
|
|
8
|
+
content:
|
|
9
|
+
constraints:
|
|
10
|
+
- 'DO NOT put business logic in Resolvers. Keep resolvers thin and delegate to Services.'
|
|
11
|
+
- 'DO NOT access raw GraphQL args/context manually when typed decorators are available. Use @Args() with typed DTOs.'
|
|
12
|
+
- 'DO NOT query the DB directly inside @ResolveField(). Use request-scoped DataLoaders.'
|
|
13
|
+
- 'DO NOT expose unauthenticated @Subscription() endpoints. Protect with guards and subscriber checks.'
|
|
14
|
+
- 'DO NOT maintain manual SDL in code-first projects. TypeScript decorators are the source of truth.'
|
|
15
|
+
guidelines:
|
|
16
|
+
- 'Use one resolver per domain entity with @Resolver(), @Query(), @Mutation(), and @ResolveField() responsibilities clearly separated.'
|
|
17
|
+
- 'Register DataLoaders as request-scoped providers to enable per-request batching without cross-request leakage.'
|
|
18
|
+
- 'Add decorator descriptions for public schema types and fields to keep generated SDL self-documenting.'
|
|
19
|
+
- 'Enforce query depth/complexity limits to prevent expensive nested query abuse.'
|
|
20
|
+
- 'Define and register custom scalars (DateTime, UUID, JSON) consistently in GraphQL module config.'
|
|
21
|
+
- 'Reuse Guards/Interceptors from REST and adapt context via GqlExecutionContext.'
|
|
22
|
+
decision_table:
|
|
23
|
+
- when: 'A field resolver loads related data (e.g., user.posts)'
|
|
24
|
+
then: 'Use @ResolveField() + request-scoped DataLoader batching'
|
|
25
|
+
avoid: 'Repository call per parent row (N+1)'
|
|
26
|
+
- when: 'Real-time push is required'
|
|
27
|
+
then: 'Use @Subscription() with Redis PubSub for multi-instance deployments'
|
|
28
|
+
avoid: 'In-memory PubSub in production'
|
|
29
|
+
- when: 'Resolver auth is required'
|
|
30
|
+
then: 'Apply @UseGuards(GqlAuthGuard) and read user from GqlExecutionContext'
|
|
31
|
+
avoid: 'Manual JWT parsing inside resolver methods'
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
id: nestjs
|
|
2
|
+
category: framework
|
|
3
|
+
tags:
|
|
4
|
+
- typescript
|
|
5
|
+
- nestjs
|
|
6
|
+
priority: 45
|
|
7
|
+
content:
|
|
8
|
+
constraints:
|
|
9
|
+
- 'DO NOT use @Res() or @Response() for manual response handling in normal routes. Return values and let Nest handle serialization/interceptors.'
|
|
10
|
+
- 'DO NOT put business logic in Controllers. Delegate to Services.'
|
|
11
|
+
- 'DO NOT use forwardRef() as a default fix for circular dependencies. Refactor module boundaries.'
|
|
12
|
+
- 'DO NOT read process.env directly in services/controllers. Use ConfigService with validated schema.'
|
|
13
|
+
- 'DO NOT use console.log for app logging. Use Nest Logger or a DI-managed logger (e.g., pino).'
|
|
14
|
+
guidelines:
|
|
15
|
+
- 'Organize by feature module and co-locate controller/service/DTO files by domain.'
|
|
16
|
+
- 'Use class-validator DTOs for request boundaries and avoid exposing persistence entities directly.'
|
|
17
|
+
- 'Register global ValidationPipe, filters, and guards in main.ts bootstrap.'
|
|
18
|
+
- 'Use custom HttpException types for domain/business failures.'
|
|
19
|
+
- 'Use @nestjs/swagger decorators for REST APIs; GraphQL schema serves as contract for GraphQL APIs.'
|
|
20
|
+
decision_table:
|
|
21
|
+
- when: 'A cross-cutting check needs handler metadata (auth/roles)'
|
|
22
|
+
then: 'Use Guards'
|
|
23
|
+
avoid: 'Middleware for authorization logic'
|
|
24
|
+
- when: 'You need response transform/caching/timing'
|
|
25
|
+
then: 'Use Interceptors'
|
|
26
|
+
avoid: 'Middleware for response-layer behavior'
|