@relipa/ai-flow-kit 0.0.6-beta.0 → 0.0.6

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.
@@ -1,224 +1,224 @@
1
- # Spring Boot AI System Prompt
2
-
3
- You are an expert Java Spring Boot developer. Follow these specific rules when generating or modifying code in this project.
4
-
5
- > **Code examples:** See `.rules/java/spring-boot-examples.md` — read it when generating code for a specific layer.
6
-
7
- ---
8
-
9
- ## Project Stack
10
-
11
- - **Java:** 17+
12
- - **Spring Boot:** 3.x
13
- - **Build Tool:** Maven (prefer) or Gradle
14
- - **ORM:** Spring Data JPA + Hibernate
15
- - **Database:** MySQL / PostgreSQL
16
- - **Testing:** JUnit 5 + Mockito + AssertJ
17
- - **Utilities:** Lombok, MapStruct
18
- - **API Style:** RESTful JSON
19
-
20
- ---
21
-
22
- ## Architecture
23
-
24
- Follow strict **Layered Architecture**:
25
-
26
- ```
27
- Controller (HTTP layer)
28
-
29
- Service (Business logic)
30
-
31
- Repository (Data access - Spring Data JPA)
32
-
33
- Entity / Domain Model
34
- ```
35
-
36
- ### Package Structure
37
-
38
- ```
39
- com.company.project/
40
- ├── controller/ # \@RestController — HTTP endpoints only
41
- ├── service/
42
- │ ├── impl/ # \@Service — business logic implementation
43
- │ └── [Interface].java
44
- ├── repository/ # \@Repository — extends JpaRepository
45
- ├── entity/ # \@Entity — JPA entities
46
- ├── dto/
47
- │ ├── request/ # Input DTOs (e.g. CreateUserRequest)
48
- │ └── response/ # Output DTOs (e.g. UserResponse)
49
- ├── mapper/ # MapStruct mappers (Entity ↔ DTO)
50
- ├── exception/
51
- │ ├── GlobalExceptionHandler.java # \@RestControllerAdvice
52
- │ └── [CustomException].java
53
- ├── config/ # \@Configuration classes
54
- └── util/ # Pure utility helpers (stateless)
55
- ```
56
-
57
- ---
58
-
59
- ## Controller Rules
60
-
61
- - Annotate with `\@RestController` + `\@RequestMapping`
62
- - **Only** handle HTTP concerns: parse request, call service, return response
63
- - Never put business logic in Controller
64
- - Always use DTOs — never expose Entity directly
65
- - Use `ResponseEntity<T>` for explicit HTTP status control
66
- - Validate input with `\@Valid` + Bean Validation annotations
67
-
68
- ---
69
-
70
- ## Service Rules
71
-
72
- - Always define an **interface**, implement in the `impl/` package
73
- - Annotate implementation with `\@Service`
74
- - All business logic lives here
75
- - Use `\@Transactional` at the method level (not class level)
76
- - Throw specific custom exceptions, not generic `RuntimeException`
77
- - Never return an Entity — always convert to DTO via Mapper
78
-
79
- ---
80
-
81
- ## Repository Rules
82
-
83
- - Extend `JpaRepository<Entity, ID>`
84
- - Use **method name queries** for simple queries
85
- - Use `\@Query` (JPQL) for complex queries — avoid native SQL unless necessary
86
- - Never add business logic here
87
- - Use `\@EntityGraph` to solve N+1 problems
88
-
89
- ---
90
-
91
- ## Entity Rules
92
-
93
- - Use Lombok: `\@Getter`, `\@Setter`, `\@NoArgsConstructor`, `\@AllArgsConstructor`, `\@Builder`
94
- - Avoid `\@Data` on entities (causes issues with `equals/hashCode` + lazy loading)
95
- - Always use `\@Table(name = "snake_case_table_name")`
96
- - Use `\@Column(name = "snake_case_column_name")` explicitly
97
- - For soft delete: add `deleted` boolean + `deletedAt` timestamp
98
- - Extend `BaseEntity` for audit fields (`createdAt`, `updatedAt`)
99
-
100
- ---
101
-
102
- ## DTO Rules
103
-
104
- - Use separate DTOs for **Request** and **Response** — never share
105
- - Use Lombok: `\@Getter`, `\@Builder`, `\@AllArgsConstructor`, `\@NoArgsConstructor`
106
- - Validate in the Request DTO with Bean Validation (`\@NotBlank`, `\@Email`, `\@NotNull`, `\@Size`)
107
- - Never expose internal fields (password hash, audit timestamps) in the Response DTO
108
-
109
- ---
110
-
111
- ## MapStruct Mapper Rules
112
-
113
- - Use `\@Mapper(componentModel = "spring")` — inject as a Spring bean
114
- - Define explicit mappings with `\@Mapping` when field names differ
115
- - Never do manual mapping (`new DTO(); dto.setField(entity.getField())`)
116
-
117
- ---
118
-
119
- ## Exception Handling
120
-
121
- - Create custom exceptions extending `RuntimeException`
122
- - Handle all exceptions in one `\@RestControllerAdvice` class
123
- - Return a consistent error response format
124
- - Never expose stack traces to the client
125
-
126
- ---
127
-
128
- ## Testing Rules
129
-
130
- ### Unit Tests (Service layer)
131
- - Test class: `[ServiceImpl]Test.java`
132
- - Mock all dependencies with `\@ExtendWith(MockitoExtension.class)` + `\@Mock`
133
- - Test happy path + edge cases + exception scenarios
134
- - Use AssertJ: `assertThat(result).isEqualTo(expected)`
135
-
136
- ### Integration Tests (Controller layer)
137
- - Use `\@SpringBootTest` + `\@AutoConfigureMockMvc`
138
- - Test full HTTP flow with `MockMvc`
139
- - Use `\@Sql` or Testcontainers for database state
140
-
141
- ---
142
-
143
- ## Naming Conventions
144
-
145
- | Element | Convention | Example |
146
- |---------|-----------|---------|
147
- | Class | PascalCase | `UserService`, `OrderController` |
148
- | Method | camelCase | `findById`, `createOrder` |
149
- | Variable | camelCase | `userResponse`, `orderId` |
150
- | Constant | UPPER_SNAKE_CASE | `MAX_RETRY_COUNT` |
151
- | Package | lowercase | `com.company.project.service` |
152
- | DB Table | snake_case | `user_orders`, `product_items` |
153
- | DB Column | snake_case | `created_at`, `user_id` |
154
- | REST endpoint | kebab-case | `/api/v1/user-profiles` |
155
- | Request DTO | `[Action][Resource]Request` | `CreateOrderRequest` |
156
- | Response DTO | `[Resource]Response` | `OrderResponse` |
157
-
158
- ---
159
-
160
- ## API Design
161
-
162
- - Version all APIs: `/api/v1/...`
163
- - Use plural nouns for resources: `/users`, `/orders`
164
- - HTTP methods: `GET` (read), `POST` (create), `PUT` (full update), `PATCH` (partial), `DELETE`
165
- - Return `201 Created` for POST, `200 OK` for GET/PUT/PATCH, `204 No Content` for DELETE
166
- - Use consistent pagination: `?page=0&size=20&sort=createdAt,desc`
167
-
168
- ```
169
- GET /api/v1/users → 200 list
170
- POST /api/v1/users → 201 created
171
- GET /api/v1/users/{id} → 200 or 404
172
- PUT /api/v1/users/{id} → 200 or 404
173
- DELETE /api/v1/users/{id} → 204 or 404
174
- GET /api/v1/users/{id}/orders → 200 nested resource
175
- ```
176
-
177
- ---
178
-
179
- ## Performance Rules
180
-
181
- - Always use pagination — never return unbounded lists
182
- - Avoid N+1: use `\@EntityGraph` or `JOIN FETCH` in JPQL
183
- - Add database indexes on frequently queried columns
184
- - Use `\@Transactional(readOnly = true)` on read-only service methods
185
- - For heavy read operations, consider projection interfaces
186
-
187
- ---
188
-
189
- ## Security Rules
190
-
191
- - Never log passwords, tokens, or sensitive PII
192
- - Hash passwords with BCrypt: `passwordEncoder.encode(rawPassword)`
193
- - Validate and sanitize all user inputs via Bean Validation
194
- - Use `\@PreAuthorize` for method-level security
195
- - Never return stack traces to API consumers
196
- - Store secrets in environment variables / Vault — never in code
197
-
198
- ---
199
-
200
- ## Logging Rules
201
-
202
- - Use SLF4J with Lombok `\@Slf4j`
203
- - `log.info` — normal business events
204
- - `log.warn` — recoverable issues (not found, validation fail)
205
- - `log.error` — unexpected exceptions (always include `ex` as the second argument)
206
- - Never log sensitive data (password, credit card, token)
207
-
208
- ---
209
-
210
- ## Common Anti-Patterns to Avoid
211
-
212
- - ❌ `\@Autowired` field injection → use constructor injection (Lombok `\@RequiredArgsConstructor`)
213
- - ❌ `\@Data` on JPA entities → use `\@Getter \@Setter` separately
214
- - ❌ Returning `Entity` directly from Controller → always use DTO
215
- - ❌ `SELECT *` or unbounded `findAll()` → always paginate
216
- - ❌ Business logic in Controller → move to Service
217
- - ❌ Catching and swallowing exceptions → handle properly or rethrow
218
- - ❌ `new RuntimeException("something")` → create a specific custom exception
219
- - ❌ Hardcoding config values → use `\@Value` or `\@ConfigurationProperties`
220
- - ❌ `\@Transactional` on Controller → only on Service methods
221
-
222
- ---
223
-
224
- When explaining changes, refer to the [Spring Boot Official Documentation](https://docs.spring.io/spring-boot/docs/current/reference/html/) and [Spring Data JPA](https://docs.spring.io/spring-data/jpa/docs/current/reference/html/) conventions.
1
+ # Spring Boot AI System Prompt
2
+
3
+ You are an expert Java Spring Boot developer. Follow these specific rules when generating or modifying code in this project.
4
+
5
+ > **Code examples:** See `.rules/java/spring-boot-examples.md` — read it when generating code for a specific layer.
6
+
7
+ ---
8
+
9
+ ## Project Stack
10
+
11
+ - **Java:** 17+
12
+ - **Spring Boot:** 3.x
13
+ - **Build Tool:** Maven (prefer) or Gradle
14
+ - **ORM:** Spring Data JPA + Hibernate
15
+ - **Database:** MySQL / PostgreSQL
16
+ - **Testing:** JUnit 5 + Mockito + AssertJ
17
+ - **Utilities:** Lombok, MapStruct
18
+ - **API Style:** RESTful JSON
19
+
20
+ ---
21
+
22
+ ## Architecture
23
+
24
+ Follow strict **Layered Architecture**:
25
+
26
+ ```
27
+ Controller (HTTP layer)
28
+
29
+ Service (Business logic)
30
+
31
+ Repository (Data access - Spring Data JPA)
32
+
33
+ Entity / Domain Model
34
+ ```
35
+
36
+ ### Package Structure
37
+
38
+ ```
39
+ com.company.project/
40
+ ├── controller/ # \@RestController — HTTP endpoints only
41
+ ├── service/
42
+ │ ├── impl/ # \@Service — business logic implementation
43
+ │ └── [Interface].java
44
+ ├── repository/ # \@Repository — extends JpaRepository
45
+ ├── entity/ # \@Entity — JPA entities
46
+ ├── dto/
47
+ │ ├── request/ # Input DTOs (e.g. CreateUserRequest)
48
+ │ └── response/ # Output DTOs (e.g. UserResponse)
49
+ ├── mapper/ # MapStruct mappers (Entity ↔ DTO)
50
+ ├── exception/
51
+ │ ├── GlobalExceptionHandler.java # \@RestControllerAdvice
52
+ │ └── [CustomException].java
53
+ ├── config/ # \@Configuration classes
54
+ └── util/ # Pure utility helpers (stateless)
55
+ ```
56
+
57
+ ---
58
+
59
+ ## Controller Rules
60
+
61
+ - Annotate with `\@RestController` + `\@RequestMapping`
62
+ - **Only** handle HTTP concerns: parse request, call service, return response
63
+ - Never put business logic in Controller
64
+ - Always use DTOs — never expose Entity directly
65
+ - Use `ResponseEntity<T>` for explicit HTTP status control
66
+ - Validate input with `\@Valid` + Bean Validation annotations
67
+
68
+ ---
69
+
70
+ ## Service Rules
71
+
72
+ - Always define an **interface**, implement in the `impl/` package
73
+ - Annotate implementation with `\@Service`
74
+ - All business logic lives here
75
+ - Use `\@Transactional` at the method level (not class level)
76
+ - Throw specific custom exceptions, not generic `RuntimeException`
77
+ - Never return an Entity — always convert to DTO via Mapper
78
+
79
+ ---
80
+
81
+ ## Repository Rules
82
+
83
+ - Extend `JpaRepository<Entity, ID>`
84
+ - Use **method name queries** for simple queries
85
+ - Use `\@Query` (JPQL) for complex queries — avoid native SQL unless necessary
86
+ - Never add business logic here
87
+ - Use `\@EntityGraph` to solve N+1 problems
88
+
89
+ ---
90
+
91
+ ## Entity Rules
92
+
93
+ - Use Lombok: `\@Getter`, `\@Setter`, `\@NoArgsConstructor`, `\@AllArgsConstructor`, `\@Builder`
94
+ - Avoid `\@Data` on entities (causes issues with `equals/hashCode` + lazy loading)
95
+ - Always use `\@Table(name = "snake_case_table_name")`
96
+ - Use `\@Column(name = "snake_case_column_name")` explicitly
97
+ - For soft delete: add `deleted` boolean + `deletedAt` timestamp
98
+ - Extend `BaseEntity` for audit fields (`createdAt`, `updatedAt`)
99
+
100
+ ---
101
+
102
+ ## DTO Rules
103
+
104
+ - Use separate DTOs for **Request** and **Response** — never share
105
+ - Use Lombok: `\@Getter`, `\@Builder`, `\@AllArgsConstructor`, `\@NoArgsConstructor`
106
+ - Validate in the Request DTO with Bean Validation (`\@NotBlank`, `\@Email`, `\@NotNull`, `\@Size`)
107
+ - Never expose internal fields (password hash, audit timestamps) in the Response DTO
108
+
109
+ ---
110
+
111
+ ## MapStruct Mapper Rules
112
+
113
+ - Use `\@Mapper(componentModel = "spring")` — inject as a Spring bean
114
+ - Define explicit mappings with `\@Mapping` when field names differ
115
+ - Never do manual mapping (`new DTO(); dto.setField(entity.getField())`)
116
+
117
+ ---
118
+
119
+ ## Exception Handling
120
+
121
+ - Create custom exceptions extending `RuntimeException`
122
+ - Handle all exceptions in one `\@RestControllerAdvice` class
123
+ - Return a consistent error response format
124
+ - Never expose stack traces to the client
125
+
126
+ ---
127
+
128
+ ## Testing Rules
129
+
130
+ ### Unit Tests (Service layer)
131
+ - Test class: `[ServiceImpl]Test.java`
132
+ - Mock all dependencies with `\@ExtendWith(MockitoExtension.class)` + `\@Mock`
133
+ - Test happy path + edge cases + exception scenarios
134
+ - Use AssertJ: `assertThat(result).isEqualTo(expected)`
135
+
136
+ ### Integration Tests (Controller layer)
137
+ - Use `\@SpringBootTest` + `\@AutoConfigureMockMvc`
138
+ - Test full HTTP flow with `MockMvc`
139
+ - Use `\@Sql` or Testcontainers for database state
140
+
141
+ ---
142
+
143
+ ## Naming Conventions
144
+
145
+ | Element | Convention | Example |
146
+ |---------|-----------|---------|
147
+ | Class | PascalCase | `UserService`, `OrderController` |
148
+ | Method | camelCase | `findById`, `createOrder` |
149
+ | Variable | camelCase | `userResponse`, `orderId` |
150
+ | Constant | UPPER_SNAKE_CASE | `MAX_RETRY_COUNT` |
151
+ | Package | lowercase | `com.company.project.service` |
152
+ | DB Table | snake_case | `user_orders`, `product_items` |
153
+ | DB Column | snake_case | `created_at`, `user_id` |
154
+ | REST endpoint | kebab-case | `/api/v1/user-profiles` |
155
+ | Request DTO | `[Action][Resource]Request` | `CreateOrderRequest` |
156
+ | Response DTO | `[Resource]Response` | `OrderResponse` |
157
+
158
+ ---
159
+
160
+ ## API Design
161
+
162
+ - Version all APIs: `/api/v1/...`
163
+ - Use plural nouns for resources: `/users`, `/orders`
164
+ - HTTP methods: `GET` (read), `POST` (create), `PUT` (full update), `PATCH` (partial), `DELETE`
165
+ - Return `201 Created` for POST, `200 OK` for GET/PUT/PATCH, `204 No Content` for DELETE
166
+ - Use consistent pagination: `?page=0&size=20&sort=createdAt,desc`
167
+
168
+ ```
169
+ GET /api/v1/users → 200 list
170
+ POST /api/v1/users → 201 created
171
+ GET /api/v1/users/{id} → 200 or 404
172
+ PUT /api/v1/users/{id} → 200 or 404
173
+ DELETE /api/v1/users/{id} → 204 or 404
174
+ GET /api/v1/users/{id}/orders → 200 nested resource
175
+ ```
176
+
177
+ ---
178
+
179
+ ## Performance Rules
180
+
181
+ - Always use pagination — never return unbounded lists
182
+ - Avoid N+1: use `\@EntityGraph` or `JOIN FETCH` in JPQL
183
+ - Add database indexes on frequently queried columns
184
+ - Use `\@Transactional(readOnly = true)` on read-only service methods
185
+ - For heavy read operations, consider projection interfaces
186
+
187
+ ---
188
+
189
+ ## Security Rules
190
+
191
+ - Never log passwords, tokens, or sensitive PII
192
+ - Hash passwords with BCrypt: `passwordEncoder.encode(rawPassword)`
193
+ - Validate and sanitize all user inputs via Bean Validation
194
+ - Use `\@PreAuthorize` for method-level security
195
+ - Never return stack traces to API consumers
196
+ - Store secrets in environment variables / Vault — never in code
197
+
198
+ ---
199
+
200
+ ## Logging Rules
201
+
202
+ - Use SLF4J with Lombok `\@Slf4j`
203
+ - `log.info` — normal business events
204
+ - `log.warn` — recoverable issues (not found, validation fail)
205
+ - `log.error` — unexpected exceptions (always include `ex` as the second argument)
206
+ - Never log sensitive data (password, credit card, token)
207
+
208
+ ---
209
+
210
+ ## Common Anti-Patterns to Avoid
211
+
212
+ - ❌ `\@Autowired` field injection → use constructor injection (Lombok `\@RequiredArgsConstructor`)
213
+ - ❌ `\@Data` on JPA entities → use `\@Getter \@Setter` separately
214
+ - ❌ Returning `Entity` directly from Controller → always use DTO
215
+ - ❌ `SELECT *` or unbounded `findAll()` → always paginate
216
+ - ❌ Business logic in Controller → move to Service
217
+ - ❌ Catching and swallowing exceptions → handle properly or rethrow
218
+ - ❌ `new RuntimeException("something")` → create a specific custom exception
219
+ - ❌ Hardcoding config values → use `\@Value` or `\@ConfigurationProperties`
220
+ - ❌ `\@Transactional` on Controller → only on Service methods
221
+
222
+ ---
223
+
224
+ When explaining changes, refer to the [Spring Boot Official Documentation](https://docs.spring.io/spring-boot/docs/current/reference/html/) and [Spring Data JPA](https://docs.spring.io/spring-data/jpa/docs/current/reference/html/) conventions.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@relipa/ai-flow-kit",
3
- "version": "0.0.6-beta.0",
3
+ "version": "0.0.6",
4
4
  "description": "All-in-one AI Flow Kit for team development with Claude AI - skills, templates, and MCP adapters",
5
5
  "author": "Relipa AI Team",
6
6
  "repository": {
package/scripts/doctor.js CHANGED
@@ -1,89 +1,89 @@
1
- const fs = require('fs-extra');
2
- const path = require('path');
3
- const chalk = require('chalk');
4
- const { detectRtk, isRtkHookConfigured } = require('./init');
5
-
6
- module.exports = async function doctor() {
7
- const projectDir = process.cwd();
8
- const errors = [];
9
- const warnings = [];
10
-
11
- console.log(chalk.blue('Running health check for AI Flow Kit...\n'));
12
-
13
- // ── Core setup ─────────────────────────────────────────────
14
- if (!(await fs.pathExists(path.join(projectDir, '.claude', 'skills')))) {
15
- errors.push('Missing `.claude/skills` directory. Did you run `aiflow init`?');
16
- } else {
17
- console.log(chalk.green('✓ .claude/skills exists'));
18
- }
19
-
20
- if (!(await fs.pathExists(path.join(projectDir, '.rules')))) {
21
- errors.push('Missing `.rules` directory.');
22
- } else {
23
- console.log(chalk.green('✓ .rules exists'));
24
- }
25
-
26
- if (!(await fs.pathExists(path.join(projectDir, 'CLAUDE.md')))) {
27
- errors.push('Missing CLAUDE.md. AI context prompt is not set up.');
28
- } else {
29
- console.log(chalk.green('✓ CLAUDE.md exists'));
30
- }
31
-
32
- // ── Version tracking ───────────────────────────────────────
33
- const stateFile = path.join(projectDir, '.aiflow', 'state.json');
34
- if (!(await fs.pathExists(stateFile))) {
35
- errors.push('Missing `.aiflow/state.json`. Version tracking is broken.');
36
- } else {
37
- const state = await fs.readJson(stateFile);
38
- console.log(chalk.green(`✓ Version tracking active (v${state.current_version})`));
39
- }
40
-
41
- // ── SessionStart hook ──────────────────────────────────────
42
- const settingsPath = path.join(projectDir, '.claude', 'settings.json');
43
- if (await fs.pathExists(settingsPath)) {
44
- const settings = await fs.readJson(settingsPath).catch(() => ({}));
45
- const hookList = settings?.hooks?.SessionStart || [];
46
- const hasSessionHook = hookList.some(h =>
47
- (h.hooks || []).some(e => typeof e.command === 'string' && e.command.includes('session-start'))
48
- );
49
- if (hasSessionHook) {
50
- console.log(chalk.green('✓ SessionStart hook configured'));
51
- } else {
52
- warnings.push('SessionStart hook not found in .claude/settings.json — run `aiflow init` to set it up.');
53
- }
54
- } else {
55
- warnings.push('Missing .claude/settings.json — run `aiflow init`.');
56
- }
57
-
58
- // ── RTK token compression ──────────────────────────────────
59
- console.log('');
60
- const rtk = await detectRtk();
61
- if (rtk.installed) {
62
- const hookOk = await isRtkHookConfigured(projectDir);
63
- if (hookOk) {
64
- console.log(chalk.green(`✓ RTK installed (${rtk.version}) — token compression active`));
65
- } else {
66
- console.log(chalk.green(`✓ RTK installed (${rtk.version})`));
67
- warnings.push('RTK is installed but hook not configured. Run `aiflow init` to enable token compression.');
68
- }
69
- } else {
70
- console.log(chalk.gray('○ RTK not installed (optional) — token compression inactive'));
71
- console.log(chalk.gray(' Install: cargo install rtk | More: https://github.com/rtk-ai/rtk'));
72
- }
73
-
74
- // ── Summary ────────────────────────────────────────────────
75
- console.log('');
76
- if (warnings.length > 0) {
77
- console.log(chalk.yellow('Warnings:'));
78
- warnings.forEach(w => console.log(chalk.yellow(` ⚠ ${w}`)));
79
- console.log('');
80
- }
81
-
82
- if (errors.length > 0) {
83
- console.log(chalk.red('Issues found:'));
84
- errors.forEach(e => console.log(chalk.red(` ✗ ${e}`)));
85
- console.log(chalk.yellow('\nTry running `aiflow init` or `aiflow update` to fix these files.'));
86
- } else {
87
- console.log(chalk.green('✨ Everything looks healthy! You are ready to fly.'));
88
- }
89
- };
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+ const chalk = require('chalk');
4
+ const { detectRtk, isRtkHookConfigured } = require('./init');
5
+
6
+ module.exports = async function doctor() {
7
+ const projectDir = process.cwd();
8
+ const errors = [];
9
+ const warnings = [];
10
+
11
+ console.log(chalk.blue('Running health check for AI Flow Kit...\n'));
12
+
13
+ // ── Core setup ─────────────────────────────────────────────
14
+ if (!(await fs.pathExists(path.join(projectDir, '.claude', 'skills')))) {
15
+ errors.push('Missing `.claude/skills` directory. Did you run `aiflow init`?');
16
+ } else {
17
+ console.log(chalk.green('✓ .claude/skills exists'));
18
+ }
19
+
20
+ if (!(await fs.pathExists(path.join(projectDir, '.rules')))) {
21
+ errors.push('Missing `.rules` directory.');
22
+ } else {
23
+ console.log(chalk.green('✓ .rules exists'));
24
+ }
25
+
26
+ if (!(await fs.pathExists(path.join(projectDir, 'CLAUDE.md')))) {
27
+ errors.push('Missing CLAUDE.md. AI context prompt is not set up.');
28
+ } else {
29
+ console.log(chalk.green('✓ CLAUDE.md exists'));
30
+ }
31
+
32
+ // ── Version tracking ───────────────────────────────────────
33
+ const stateFile = path.join(projectDir, '.aiflow', 'state.json');
34
+ if (!(await fs.pathExists(stateFile))) {
35
+ errors.push('Missing `.aiflow/state.json`. Version tracking is broken.');
36
+ } else {
37
+ const state = await fs.readJson(stateFile);
38
+ console.log(chalk.green(`✓ Version tracking active (v${state.current_version})`));
39
+ }
40
+
41
+ // ── SessionStart hook ──────────────────────────────────────
42
+ const settingsPath = path.join(projectDir, '.claude', 'settings.json');
43
+ if (await fs.pathExists(settingsPath)) {
44
+ const settings = await fs.readJson(settingsPath).catch(() => ({}));
45
+ const hookList = settings?.hooks?.SessionStart || [];
46
+ const hasSessionHook = hookList.some(h =>
47
+ (h.hooks || []).some(e => typeof e.command === 'string' && e.command.includes('session-start'))
48
+ );
49
+ if (hasSessionHook) {
50
+ console.log(chalk.green('✓ SessionStart hook configured'));
51
+ } else {
52
+ warnings.push('SessionStart hook not found in .claude/settings.json — run `aiflow init` to set it up.');
53
+ }
54
+ } else {
55
+ warnings.push('Missing .claude/settings.json — run `aiflow init`.');
56
+ }
57
+
58
+ // ── RTK token compression ──────────────────────────────────
59
+ console.log('');
60
+ const rtk = await detectRtk();
61
+ if (rtk.installed) {
62
+ const hookOk = await isRtkHookConfigured(projectDir);
63
+ if (hookOk) {
64
+ console.log(chalk.green(`✓ RTK installed (${rtk.version}) — token compression active`));
65
+ } else {
66
+ console.log(chalk.green(`✓ RTK installed (${rtk.version})`));
67
+ warnings.push('RTK is installed but hook not configured. Run `aiflow init` to enable token compression.');
68
+ }
69
+ } else {
70
+ console.log(chalk.gray('○ RTK not installed (optional) — token compression inactive'));
71
+ console.log(chalk.gray(' Install: cargo install rtk | More: https://github.com/rtk-ai/rtk'));
72
+ }
73
+
74
+ // ── Summary ────────────────────────────────────────────────
75
+ console.log('');
76
+ if (warnings.length > 0) {
77
+ console.log(chalk.yellow('Warnings:'));
78
+ warnings.forEach(w => console.log(chalk.yellow(` ⚠ ${w}`)));
79
+ console.log('');
80
+ }
81
+
82
+ if (errors.length > 0) {
83
+ console.log(chalk.red('Issues found:'));
84
+ errors.forEach(e => console.log(chalk.red(` ✗ ${e}`)));
85
+ console.log(chalk.yellow('\nTry running `aiflow init` or `aiflow update` to fix these files.'));
86
+ } else {
87
+ console.log(chalk.green('✨ Everything looks healthy! You are ready to fly.'));
88
+ }
89
+ };