@ai-content-space/loopx 0.1.2 → 0.1.4

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.
Files changed (69) hide show
  1. package/README.md +422 -57
  2. package/README.zh-CN.md +485 -0
  3. package/assets/logo.svg +89 -0
  4. package/package.json +5 -1
  5. package/plugins/loopx/.codex-plugin/plugin.json +1 -1
  6. package/plugins/loopx/scripts/plugin-install.test.mjs +14 -0
  7. package/plugins/loopx/skills/archive/SKILL.md +49 -0
  8. package/plugins/loopx/skills/build/SKILL.md +111 -9
  9. package/plugins/loopx/skills/clarify/SKILL.md +129 -8
  10. package/plugins/loopx/skills/debug/SKILL.md +296 -0
  11. package/plugins/loopx/skills/debug/condition-based-waiting.md +115 -0
  12. package/plugins/loopx/skills/debug/defense-in-depth.md +122 -0
  13. package/plugins/loopx/skills/debug/find-polluter.sh +63 -0
  14. package/plugins/loopx/skills/debug/root-cause-tracing.md +169 -0
  15. package/plugins/loopx/skills/go-style/SKILL.md +71 -0
  16. package/plugins/loopx/skills/kratos/SKILL.md +74 -0
  17. package/plugins/loopx/skills/kratos/references/advanced-features.md +314 -0
  18. package/plugins/loopx/skills/kratos/references/architecture.md +488 -0
  19. package/plugins/loopx/skills/kratos/references/configuration.md +399 -0
  20. package/plugins/loopx/skills/kratos/references/http-customization.md +512 -0
  21. package/plugins/loopx/skills/kratos/references/middleware-logging.md +400 -0
  22. package/plugins/loopx/skills/kratos/references/proto-api-design.md +432 -0
  23. package/plugins/loopx/skills/kratos/references/security-auth.md +411 -0
  24. package/plugins/loopx/skills/kratos/references/troubleshooting.md +385 -0
  25. package/plugins/loopx/skills/plan/SKILL.md +24 -3
  26. package/plugins/loopx/skills/review/SKILL.md +98 -1
  27. package/plugins/loopx/skills/tdd/SKILL.md +371 -0
  28. package/plugins/loopx/skills/tdd/testing-anti-patterns.md +299 -0
  29. package/plugins/loopx/skills/verify/SKILL.md +139 -0
  30. package/scripts/codex-stop-hook.mjs +71 -0
  31. package/scripts/codex-workflow-hook.mjs +248 -0
  32. package/skills/archive/SKILL.md +49 -0
  33. package/skills/build/SKILL.md +111 -9
  34. package/skills/clarify/SKILL.md +129 -8
  35. package/skills/debug/SKILL.md +296 -0
  36. package/skills/debug/condition-based-waiting.md +115 -0
  37. package/skills/debug/defense-in-depth.md +122 -0
  38. package/skills/debug/find-polluter.sh +63 -0
  39. package/skills/debug/root-cause-tracing.md +169 -0
  40. package/skills/go-style/SKILL.md +71 -0
  41. package/skills/kratos/SKILL.md +74 -0
  42. package/skills/kratos/references/advanced-features.md +314 -0
  43. package/skills/kratos/references/architecture.md +488 -0
  44. package/skills/kratos/references/configuration.md +399 -0
  45. package/skills/kratos/references/http-customization.md +512 -0
  46. package/skills/kratos/references/middleware-logging.md +400 -0
  47. package/skills/kratos/references/proto-api-design.md +432 -0
  48. package/skills/kratos/references/security-auth.md +411 -0
  49. package/skills/kratos/references/troubleshooting.md +385 -0
  50. package/skills/plan/SKILL.md +20 -3
  51. package/skills/review/SKILL.md +98 -1
  52. package/skills/tdd/SKILL.md +371 -0
  53. package/skills/tdd/testing-anti-patterns.md +299 -0
  54. package/skills/verify/SKILL.md +139 -0
  55. package/src/build-runtime.mjs +311 -26
  56. package/src/build-stop-gate.mjs +94 -0
  57. package/src/cli.mjs +57 -5
  58. package/src/codex-exec-runtime.mjs +105 -5
  59. package/src/context-manifest.mjs +172 -0
  60. package/src/html-views.mjs +316 -0
  61. package/src/install-discovery.mjs +352 -5
  62. package/src/next-skill.mjs +57 -5
  63. package/src/plan-runtime.mjs +102 -122
  64. package/src/review-runtime.mjs +558 -0
  65. package/src/runtime-maintenance.mjs +429 -14
  66. package/src/template-governance.mjs +223 -0
  67. package/src/workflow.mjs +2341 -120
  68. package/src/workspace-context.mjs +166 -0
  69. package/src/workspace-memory.mjs +69 -0
@@ -0,0 +1,432 @@
1
+ # Proto API Design
2
+
3
+ Guide for defining HTTP APIs with protobuf in Kratos.
4
+
5
+ ## When to Use
6
+
7
+ - Creating new service APIs
8
+ - Defining HTTP routes with path variables
9
+ - Setting up field validation
10
+ - Configuring buf generation
11
+
12
+ ---
13
+
14
+ ## HTTP Proto Definition Patterns
15
+
16
+ ### Basic Path Variables
17
+
18
+ ```protobuf
19
+ // Simple variable extraction
20
+ message GetUserRequest {
21
+ string user_id = 1; // Extracted from URL
22
+ }
23
+
24
+ service UserService {
25
+ rpc GetUser(GetUserRequest) returns (User) {
26
+ option (google.api.http) = {
27
+ get: "/v1/users/{user_id}"
28
+ };
29
+ }
30
+ }
31
+ // URL: GET /v1/users/123 → user_id = "123"
32
+ ```
33
+
34
+ ### Pattern Matching
35
+
36
+ Use patterns to restrict URL format and extract structured data:
37
+
38
+ ```protobuf
39
+ // Single segment match (*)
40
+ message ListUsersRequest {
41
+ string parent = 1; // Value will be "projects/123"
42
+ }
43
+
44
+ service UserService {
45
+ rpc ListUsers(ListUsersRequest) returns (ListUsersResponse) {
46
+ option (google.api.http) = {
47
+ get: "/v1/{parent=projects/*}/users"
48
+ };
49
+ }
50
+ }
51
+ // URL: GET /v1/projects/123/users → parent = "projects/123"
52
+
53
+ // Multi-segment match (**)
54
+ message GetResourceRequest {
55
+ string path = 1; // Value will be "a/b/c/d"
56
+ }
57
+
58
+ service ResourceService {
59
+ rpc GetResource(GetResourceRequest) returns (Resource) {
60
+ option (google.api.http) = {
61
+ get: "/v1/{path=**}"
62
+ };
63
+ }
64
+ }
65
+ // URL: GET /v1/a/b/c/d → path = "a/b/c/d"
66
+ ```
67
+
68
+ ### HTTP Method Mapping
69
+
70
+ ```protobuf
71
+ // GET - query parameters from URL
72
+ rpc GetUser(GetUserRequest) returns (User) {
73
+ option (google.api.http) = {
74
+ get: "/v1/users/{user_id}"
75
+ };
76
+ }
77
+
78
+ // POST - body contains resource
79
+ rpc CreateUser(CreateUserRequest) returns (User) {
80
+ option (google.api.http) = {
81
+ post: "/v1/users"
82
+ body: "user" // Map 'user' field to request body
83
+ };
84
+ }
85
+
86
+ // PUT - full resource replacement
87
+ rpc UpdateUser(UpdateUserRequest) returns (User) {
88
+ option (google.api.http) = {
89
+ put: "/v1/users/{user_id}"
90
+ body: "user"
91
+ };
92
+ }
93
+
94
+ // PATCH - partial update
95
+ rpc PatchUser(PatchUserRequest) returns (User) {
96
+ option (google.api.http) = {
97
+ patch: "/v1/users/{user_id}"
98
+ body: "user"
99
+ };
100
+ }
101
+
102
+ // DELETE - no body
103
+ rpc DeleteUser(DeleteUserRequest) returns (google.protobuf.Empty) {
104
+ option (google.api.http) = {
105
+ delete: "/v1/users/{user_id}"
106
+ };
107
+ }
108
+ ```
109
+
110
+ ### Custom Methods
111
+
112
+ Use `:` suffix for custom operations beyond CRUD:
113
+
114
+ ```protobuf
115
+ // Custom action on a resource
116
+ rpc ActivateUser(ActivateUserRequest) returns (User) {
117
+ option (google.api.http) = {
118
+ post: "/v1/users/{name}:activate"
119
+ body: "*"
120
+ };
121
+ }
122
+ // URL: POST /v1/users/123:activate
123
+
124
+ // Batch operations
125
+ rpc BatchCreateUsers(BatchCreateUsersRequest) returns (BatchCreateUsersResponse) {
126
+ option (google.api.http) = {
127
+ post: "/v1/users:batchCreate"
128
+ body: "requests"
129
+ };
130
+ }
131
+ // URL: POST /v1/users:batchCreate
132
+ ```
133
+
134
+ ### Multiple Routes (additional_bindings)
135
+
136
+ One RPC can serve multiple URL patterns:
137
+
138
+ ```protobuf
139
+ rpc GetResource(GetResourceRequest) returns (Resource) {
140
+ option (google.api.http) = {
141
+ get: "/v1/{name=projects/*/resources/*}"
142
+ additional_bindings {
143
+ get: "/v1/{name=locations/*/resources/*}"
144
+ }
145
+ };
146
+ }
147
+ // URL: GET /v1/projects/123/resources/456
148
+ // URL: GET /v1/locations/us-east1/resources/456
149
+ ```
150
+
151
+ ### Pagination Pattern
152
+
153
+ Standard pagination fields:
154
+
155
+ ```protobuf
156
+ message ListBooksRequest {
157
+ string parent = 1; // "shelves/shelf1"
158
+ int32 page_size = 2; // Max results per page
159
+ string page_token = 3; // Token from previous response
160
+ string order_by = 4; // Optional: "name desc"
161
+ string filter = 5; // Optional: "age>18"
162
+ }
163
+
164
+ message ListBooksResponse {
165
+ repeated Book books = 1;
166
+ string next_page_token = 2; // Empty = no more data
167
+ int32 total_size = 3; // Optional: total count
168
+ }
169
+
170
+ service BookService {
171
+ rpc ListBooks(ListBooksRequest) returns (ListBooksResponse) {
172
+ option (google.api.http) = {
173
+ get: "/v1/{parent=shelves/*}/books"
174
+ };
175
+ }
176
+ }
177
+ ```
178
+
179
+ ---
180
+
181
+ ## buf.validate Field Validation
182
+
183
+ Use buf's protovalidate for runtime validation:
184
+
185
+ ### String Validation
186
+
187
+ ```protobuf
188
+ message User {
189
+ string name = 1 [
190
+ (buf.validate.field).string.min_len = 1,
191
+ (buf.validate.field).string.max_len = 100,
192
+ (buf.validate.field).string.pattern = "^[a-zA-Z]+$"
193
+ ];
194
+
195
+ string email = 2 [
196
+ (buf.validate.field).string.email = true
197
+ ];
198
+
199
+ string website = 3 [
200
+ (buf.validate.field).string.uri = true
201
+ ];
202
+ }
203
+ ```
204
+
205
+ ### Integer Validation
206
+
207
+ ```protobuf
208
+ message Product {
209
+ int32 quantity = 1 [
210
+ (buf.validate.field).int32.gte = 0,
211
+ (buf.validate.field).int32.lte = 1000
212
+ ];
213
+
214
+ int32 status = 2 [
215
+ (buf.validate.field).int32.in = [0, 1, 2, 3]
216
+ ];
217
+ }
218
+ ```
219
+
220
+ ### Duration Validation
221
+
222
+ ```protobuf
223
+ import "google/protobuf/duration.proto";
224
+
225
+ message Server {
226
+ google.protobuf.Duration timeout = 1 [
227
+ (buf.validate.field).required = true,
228
+ (buf.validate.field).duration = {
229
+ gt: {seconds: 1} // Greater than 1 second
230
+ lte: {seconds: 600} // Less than or equal 10 minutes
231
+ }
232
+ ];
233
+ }
234
+ ```
235
+
236
+ ### Enum Validation
237
+
238
+ ```protobuf
239
+ enum Status {
240
+ UNKNOWN = 0;
241
+ ACTIVE = 1;
242
+ INACTIVE = 2;
243
+ }
244
+
245
+ message User {
246
+ Status status = 1 [
247
+ (buf.validate.field).enum.defined_only = true,
248
+ (buf.validate.field).enum.in = [1, 2]
249
+ ];
250
+ }
251
+ ```
252
+
253
+ ### Required Fields
254
+
255
+ ```protobuf
256
+ message Request {
257
+ string name = 1 [(buf.validate.field).required = true];
258
+ }
259
+ ```
260
+
261
+ ---
262
+
263
+ ## buf.gen.yaml Configuration
264
+
265
+ Example configuration for Kratos projects:
266
+
267
+ ```yaml
268
+ version: v1
269
+ managed:
270
+ enabled: true
271
+ override:
272
+ - file_option: go_package
273
+ module: buf.build/bufbuild/protovalidate
274
+ value: buf.build/go/protovalidate
275
+
276
+ plugins:
277
+ # Go struct generation
278
+ - remote: buf.build/protocolbuffers/go
279
+ out: api
280
+ opt: paths=source_relative
281
+
282
+ # gRPC service generation
283
+ - remote: buf.build/grpc/go
284
+ out: api
285
+ opt:
286
+ - paths=source_relative
287
+ - require_unimplemented_servers=false
288
+
289
+ # Validation code generation
290
+ - remote: buf.build/bufbuild/validate-go
291
+ out: api
292
+ opt: paths=source_relative
293
+
294
+ # OpenAPI documentation
295
+ - remote: buf.build/community/google-gnostic-openapi
296
+ out: docs
297
+ opt:
298
+ - paths=source_relative
299
+ - naming=proto
300
+
301
+ # Kratos HTTP gateway (local plugin)
302
+ - local: protoc-gen-go-http
303
+ out: api
304
+ opt: paths=source_relative
305
+
306
+ # Kratos error codes (local plugin)
307
+ - local: protoc-gen-go-errors
308
+ out: api
309
+ opt: paths=source_relative
310
+ ```
311
+
312
+ **Install local plugins:**
313
+ ```bash
314
+ kratos upgrade # Installs protoc-gen-go-http, protoc-gen-go-errors
315
+ ```
316
+
317
+ ---
318
+
319
+ ## Critical Pitfall: Route Override Order
320
+
321
+ **Problem:** Route definitions are processed in order. A generic route can shadow a specific one.
322
+
323
+ ```protobuf
324
+ // WRONG ORDER - specific route shadowed
325
+ rpc GetUser(GetUserRequest) returns (User) {
326
+ option (google.api.http) = {get: "/v1/user/{user_id}"}; // Generic
327
+ }
328
+ rpc GetProfile(GetProfileRequest) returns (Profile) {
329
+ option (google.api.http) = {get: "/v1/user/profile"}; // Specific - shadowed!
330
+ }
331
+
332
+ // CORRECT ORDER - specific route first
333
+ rpc GetProfile(GetProfileRequest) returns (Profile) {
334
+ option (google.api.http) = {get: "/v1/user/profile"}; // Specific first
335
+ }
336
+ rpc GetUser(GetUserRequest) returns (User) {
337
+ option (google.api.http) = {get: "/v1/user/{user_id}"}; // Generic last
338
+ }
339
+ ```
340
+
341
+ **Why this matters:** HTTP routers match in order. `{user_id}` can match "profile", causing unexpected behavior.
342
+
343
+ ---
344
+
345
+ ## Error Code Design
346
+
347
+ Follow industry standards for error codes:
348
+
349
+ ### Alibaba Format (5-digit string)
350
+
351
+ ```
352
+ [A/B/C][NNNN]
353
+
354
+ A = User error (bad request)
355
+ B = System error (business logic)
356
+ C = Third-party error (external service)
357
+
358
+ NNNN = Error number within category
359
+ ```
360
+
361
+ Examples:
362
+ - `A0001` - Invalid parameter (user error)
363
+ - `B0101` - Database connection failed (system error)
364
+ - `C0201` - Payment gateway timeout (third-party error)
365
+
366
+ ### Proto Definition
367
+
368
+ ```protobuf
369
+ enum ErrorReason {
370
+ USER_NOT_FOUND = 0;
371
+ INVALID_PARAMETER = 1;
372
+ INTERNAL_ERROR = 2;
373
+ }
374
+
375
+ // In service code:
376
+ var ErrUserNotFound = errors.NotFound(
377
+ ErrorReason_USER_NOT_FOUND.String(),
378
+ "user not found"
379
+ )
380
+ ```
381
+
382
+ ### HTTP Error Response
383
+
384
+ ```json
385
+ {
386
+ "code": "A0001",
387
+ "message": "Invalid parameter: user_id must be positive",
388
+ "details": "See documentation at https://api.example.com/docs/errors/A0001"
389
+ }
390
+ ```
391
+
392
+ ---
393
+
394
+ ## OpenAPI Documentation
395
+
396
+ buf.gen.yaml generates OpenAPI specs automatically:
397
+
398
+ ```yaml
399
+ - remote: buf.build/community/google-gnostic-openapi
400
+ out: docs
401
+ opt:
402
+ - paths=source_relative
403
+ - naming=proto
404
+ ```
405
+
406
+ Add proto-level documentation:
407
+
408
+ ```protobuf
409
+ import "gnostic/openapi/v3/annotations.proto";
410
+
411
+ option (gnostic.openapi.v3.document) = {
412
+ info: {
413
+ title: "My API"
414
+ version: "1.0.0"
415
+ description: "API description"
416
+ }
417
+ servers: [
418
+ {url: "https://api.example.com", description: "Production"}
419
+ ]
420
+ };
421
+
422
+ service MyService {
423
+ rpc GetUser(GetUserRequest) returns (User) {
424
+ option (google.api.http) = {get: "/v1/users/{user_id}"};
425
+ option (gnostic.openapi.v3.operation) = {
426
+ operation_id: "getUser"
427
+ summary: "Get a user by ID"
428
+ description: "Returns the user with the specified ID"
429
+ };
430
+ }
431
+ }
432
+ ```