@ai-content-space/loopx 0.1.1 → 0.1.3
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 +343 -56
- package/README.zh-CN.md +392 -0
- package/package.json +4 -1
- package/plugins/loopx/.codex-plugin/plugin.json +1 -1
- package/plugins/loopx/scripts/plugin-install.test.mjs +1 -0
- package/plugins/loopx/skills/archive/SKILL.md +39 -0
- package/plugins/loopx/skills/build/SKILL.md +111 -9
- package/plugins/loopx/skills/clarify/SKILL.md +121 -1
- package/plugins/loopx/skills/debug/SKILL.md +296 -0
- package/plugins/loopx/skills/debug/condition-based-waiting.md +115 -0
- package/plugins/loopx/skills/debug/defense-in-depth.md +122 -0
- package/plugins/loopx/skills/debug/find-polluter.sh +63 -0
- package/plugins/loopx/skills/debug/root-cause-tracing.md +169 -0
- package/plugins/loopx/skills/go-style/SKILL.md +71 -0
- package/plugins/loopx/skills/kratos/SKILL.md +74 -0
- package/plugins/loopx/skills/kratos/references/advanced-features.md +314 -0
- package/plugins/loopx/skills/kratos/references/architecture.md +488 -0
- package/plugins/loopx/skills/kratos/references/configuration.md +399 -0
- package/plugins/loopx/skills/kratos/references/http-customization.md +512 -0
- package/plugins/loopx/skills/kratos/references/middleware-logging.md +400 -0
- package/plugins/loopx/skills/kratos/references/proto-api-design.md +432 -0
- package/plugins/loopx/skills/kratos/references/security-auth.md +411 -0
- package/plugins/loopx/skills/kratos/references/troubleshooting.md +385 -0
- package/plugins/loopx/skills/plan/SKILL.md +22 -2
- package/plugins/loopx/skills/review/SKILL.md +98 -1
- package/plugins/loopx/skills/tdd/SKILL.md +371 -0
- package/plugins/loopx/skills/tdd/testing-anti-patterns.md +299 -0
- package/plugins/loopx/skills/verify/SKILL.md +139 -0
- package/scripts/codex-stop-hook.mjs +71 -0
- package/scripts/codex-workflow-hook.mjs +153 -0
- package/skills/archive/SKILL.md +39 -0
- package/skills/build/SKILL.md +111 -9
- package/skills/clarify/SKILL.md +121 -1
- package/skills/debug/SKILL.md +296 -0
- package/skills/debug/condition-based-waiting.md +115 -0
- package/skills/debug/defense-in-depth.md +122 -0
- package/skills/debug/find-polluter.sh +63 -0
- package/skills/debug/root-cause-tracing.md +169 -0
- package/skills/go-style/SKILL.md +71 -0
- package/skills/kratos/SKILL.md +74 -0
- package/skills/kratos/references/advanced-features.md +314 -0
- package/skills/kratos/references/architecture.md +488 -0
- package/skills/kratos/references/configuration.md +399 -0
- package/skills/kratos/references/http-customization.md +512 -0
- package/skills/kratos/references/middleware-logging.md +400 -0
- package/skills/kratos/references/proto-api-design.md +432 -0
- package/skills/kratos/references/security-auth.md +411 -0
- package/skills/kratos/references/troubleshooting.md +385 -0
- package/skills/plan/SKILL.md +22 -2
- package/skills/review/SKILL.md +98 -1
- package/skills/tdd/SKILL.md +371 -0
- package/skills/tdd/testing-anti-patterns.md +299 -0
- package/skills/verify/SKILL.md +139 -0
- package/src/build-runtime.mjs +303 -26
- package/src/build-stop-gate.mjs +94 -0
- package/src/cli.mjs +51 -8
- package/src/codex-exec-runtime.mjs +105 -5
- package/src/context-manifest.mjs +172 -0
- package/src/install-discovery.mjs +352 -5
- package/src/next-skill.mjs +85 -0
- package/src/plan-runtime.mjs +100 -122
- package/src/review-runtime.mjs +378 -0
- package/src/runtime-maintenance.mjs +428 -14
- package/src/template-governance.mjs +223 -0
- package/src/workflow.mjs +1947 -118
- package/src/workspace-context.mjs +166 -0
- package/src/workspace-memory.mjs +69 -0
- package/templates/plan.md +6 -0
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
# Troubleshooting
|
|
2
|
+
|
|
3
|
+
Guide for common Kratos issues and debugging techniques.
|
|
4
|
+
|
|
5
|
+
## When to Use
|
|
6
|
+
|
|
7
|
+
- Route override problems
|
|
8
|
+
- Zero-value field issues
|
|
9
|
+
- Validation errors on partial updates
|
|
10
|
+
- Enum display issues
|
|
11
|
+
- Debugging runtime behavior
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Route Override Issue
|
|
16
|
+
|
|
17
|
+
### Problem
|
|
18
|
+
|
|
19
|
+
Generic routes shadow specific routes when defined first:
|
|
20
|
+
|
|
21
|
+
```protobuf
|
|
22
|
+
// WRONG: specific route shadowed
|
|
23
|
+
rpc GetUser(GetUserRequest) returns (User) {
|
|
24
|
+
option (google.api.http) = {get: "/v1/user/{user_id}"}; // Matches "profile"!
|
|
25
|
+
}
|
|
26
|
+
rpc GetProfile(GetProfileRequest) returns (Profile) {
|
|
27
|
+
option (google.api.http) = {get: "/v1/user/profile"}; // Never matched
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Solution
|
|
32
|
+
|
|
33
|
+
Define specific routes before generic ones:
|
|
34
|
+
|
|
35
|
+
```protobuf
|
|
36
|
+
// CORRECT: specific route first
|
|
37
|
+
rpc GetProfile(GetProfileRequest) returns (Profile) {
|
|
38
|
+
option (google.api.http) = {get: "/v1/user/profile"}; // Matches first
|
|
39
|
+
}
|
|
40
|
+
rpc GetUser(GetUserRequest) returns (User) {
|
|
41
|
+
option (google.api.http) = {get: "/v1/user/{user_id}"}; // Matches remaining
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Why this matters:** HTTP routers match in order. `{user_id}` is a wildcard that matches any string including "profile".
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Zero-Value Field Issue
|
|
50
|
+
|
|
51
|
+
### Problem
|
|
52
|
+
|
|
53
|
+
Protobuf by default omits fields with zero values (empty string, 0, false, nil):
|
|
54
|
+
|
|
55
|
+
```go
|
|
56
|
+
// Proto message
|
|
57
|
+
message User {
|
|
58
|
+
string name = 1;
|
|
59
|
+
int32 age = 2;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Response
|
|
63
|
+
{name: "", age: 0}
|
|
64
|
+
|
|
65
|
+
// JSON output: {} // Empty! All fields omitted.
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Solution 1: EmitUnpopulated
|
|
69
|
+
|
|
70
|
+
```go
|
|
71
|
+
import "google.golang.org/protobuf/encoding/protojson"
|
|
72
|
+
|
|
73
|
+
var MarshalOptions = protojson.MarshalOptions{
|
|
74
|
+
EmitUnpopulated: true, // Include zero values
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Custom codec
|
|
78
|
+
func (codec) Marshal(v interface{}) ([]byte, error) {
|
|
79
|
+
if m, ok := v.(proto.Message); ok {
|
|
80
|
+
return MarshalOptions.Marshal(m)
|
|
81
|
+
}
|
|
82
|
+
return json.Marshal(v)
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Solution 2: anypb.New Wrapper
|
|
87
|
+
|
|
88
|
+
```go
|
|
89
|
+
import "google.golang.org/protobuf/types/known/anypb"
|
|
90
|
+
|
|
91
|
+
payload, err := anypb.New(m)
|
|
92
|
+
reply.Data = payload
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**Note:** Adds `@type` field: `{"@type": "type.googleapis.com/...", "value": {...}}`
|
|
96
|
+
|
|
97
|
+
### Solution 3: Remove omitempty
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
# Makefile - remove omitempty from pb.go tags
|
|
101
|
+
find ./api -name '*.pb.go' -exec sed -i -e "s/,omitempty/,optional/g" {} \;
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Partial Update Validation Issue
|
|
107
|
+
|
|
108
|
+
### Problem
|
|
109
|
+
|
|
110
|
+
Validate middleware checks all fields, but partial updates (PATCH) may only send some:
|
|
111
|
+
|
|
112
|
+
```protobuf
|
|
113
|
+
message UpdateUserRequest {
|
|
114
|
+
string user_id = 1 [(buf.validate.field).string.min_len = 1]; // Required
|
|
115
|
+
string name = 2 [(buf.validate.field).string.min_len = 1]; // Required
|
|
116
|
+
string email = 3 [(buf.validate.field).string.email = true]; // Required
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// PATCH request only sends name
|
|
120
|
+
{name: "John", user_id: "123", email: ""} // Fails validation! email is required.
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Solution 1: Whitelist Operations
|
|
124
|
+
|
|
125
|
+
Skip validation for specific operations:
|
|
126
|
+
|
|
127
|
+
```go
|
|
128
|
+
func WhitelistValidateMiddleware(whitelist map[string]bool) middleware.Middleware {
|
|
129
|
+
return func(handler middleware.Handler) middleware.Handler {
|
|
130
|
+
return func(ctx context.Context, req interface{}) (interface{}, error) {
|
|
131
|
+
if tr, ok := transport.FromServerContext(ctx); ok {
|
|
132
|
+
if whitelist[tr.Operation()] {
|
|
133
|
+
return handler(ctx, req) // Skip validation
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
// Normal validation
|
|
137
|
+
if err := validator.Validate(req); err != nil {
|
|
138
|
+
return nil, err
|
|
139
|
+
}
|
|
140
|
+
return handler(ctx, req)
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Usage
|
|
146
|
+
whitelist := map[string]bool{
|
|
147
|
+
"/api.v1.UserService/PatchUser": true,
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Solution 2: Manual Validation
|
|
152
|
+
|
|
153
|
+
Validate only changed fields in biz layer:
|
|
154
|
+
|
|
155
|
+
```go
|
|
156
|
+
func (uc *UserUseCase) PatchUser(ctx context.Context, req *v1.PatchUserRequest) error {
|
|
157
|
+
// Only validate if field is set
|
|
158
|
+
if req.Name != "" && len(req.Name) < 1 {
|
|
159
|
+
return errors.New(400, "INVALID_NAME", "name too short")
|
|
160
|
+
}
|
|
161
|
+
if req.Email != "" && !isValidEmail(req.Email) {
|
|
162
|
+
return errors.New(400, "INVALID_EMAIL", "invalid email")
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Enum as String Issue
|
|
170
|
+
|
|
171
|
+
### Problem
|
|
172
|
+
|
|
173
|
+
Custom ResponseEncoder may display enums as strings instead of numbers:
|
|
174
|
+
|
|
175
|
+
```protobuf
|
|
176
|
+
enum Status {
|
|
177
|
+
UNKNOWN = 0;
|
|
178
|
+
ACTIVE = 1;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Expected JSON: {"status": 1}
|
|
182
|
+
// Actual JSON: {"status": "ACTIVE"} // String!
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Solution: UseEnumNumbers
|
|
186
|
+
|
|
187
|
+
```go
|
|
188
|
+
var MarshalOptions = protojson.MarshalOptions{
|
|
189
|
+
EmitUnpopulated: true,
|
|
190
|
+
UseEnumNumbers: true, // Enums as numbers
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
type codec struct{}
|
|
194
|
+
|
|
195
|
+
func (codec) Marshal(v interface{}) ([]byte, error) {
|
|
196
|
+
if m, ok := v.(proto.Message); ok {
|
|
197
|
+
return MarshalOptions.Marshal(m)
|
|
198
|
+
}
|
|
199
|
+
return json.Marshal(v)
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
func init() {
|
|
203
|
+
encoding.RegisterCodec(codec{})
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## HTTP Proto Unsupported Scenarios
|
|
210
|
+
|
|
211
|
+
### Problem
|
|
212
|
+
|
|
213
|
+
Some HTTP features can't be expressed in proto:
|
|
214
|
+
|
|
215
|
+
- File upload (multipart/form-data)
|
|
216
|
+
- WebSocket upgrade
|
|
217
|
+
- Server-Sent Events (SSE)
|
|
218
|
+
- Custom authentication flows
|
|
219
|
+
|
|
220
|
+
### Solution: Custom Routes
|
|
221
|
+
|
|
222
|
+
```go
|
|
223
|
+
func NewHTTPServer(c *conf.Server, svc *service.MyService) *http.Server {
|
|
224
|
+
srv := http.NewServer(
|
|
225
|
+
http.Address(c.Http.Addr),
|
|
226
|
+
http.Middleware(
|
|
227
|
+
recovery.Recovery(),
|
|
228
|
+
auth.Token(),
|
|
229
|
+
),
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
// Proto-generated routes
|
|
233
|
+
v1.RegisterMyServiceHTTPServer(srv, svc)
|
|
234
|
+
|
|
235
|
+
// Custom routes (inherit middleware)
|
|
236
|
+
route := srv.Route("/")
|
|
237
|
+
route.POST("/v1/upload", svc.UploadFile)
|
|
238
|
+
route.GET("/v1/ws", svc.WebSocketHandler)
|
|
239
|
+
|
|
240
|
+
return srv
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
func (s *MyService) UploadFile(ctx http.Context) error {
|
|
244
|
+
http.SetOperation(ctx, "/upload.v1.UploadService/Upload")
|
|
245
|
+
|
|
246
|
+
// Use ctx.Middleware to inherit server middleware
|
|
247
|
+
h := ctx.Middleware(func(ctx context.Context, req interface{}) (interface{}, error) {
|
|
248
|
+
return s.uc.Upload(ctx, req.(*UploadRequest))
|
|
249
|
+
})
|
|
250
|
+
|
|
251
|
+
resp, err := h(ctx, parseUploadRequest(ctx))
|
|
252
|
+
return ctx.JSON(200, resp)
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## Debugging Tools
|
|
259
|
+
|
|
260
|
+
### statsviz - Real-time Runtime Metrics
|
|
261
|
+
|
|
262
|
+
Visualize Go runtime metrics in browser:
|
|
263
|
+
|
|
264
|
+
```go
|
|
265
|
+
import "github.com/arl/statsviz"
|
|
266
|
+
|
|
267
|
+
func newApp(logger log.Logger, hs *http.Server, gs *grpc.Server) *kratos.App {
|
|
268
|
+
statsviz.RegisterDefault() // Register /debug/statsviz/
|
|
269
|
+
|
|
270
|
+
return kratos.New(
|
|
271
|
+
kratos.Name("my-app"),
|
|
272
|
+
kratos.Server(hs, gs),
|
|
273
|
+
)
|
|
274
|
+
}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
Access at: `http://localhost:8000/debug/statsviz/`
|
|
278
|
+
|
|
279
|
+
Shows:
|
|
280
|
+
- Heap allocation
|
|
281
|
+
- Goroutine count
|
|
282
|
+
- GC pauses
|
|
283
|
+
- CPU usage
|
|
284
|
+
- Scheduler latency
|
|
285
|
+
|
|
286
|
+
### fgtrace - Timeline Profiler
|
|
287
|
+
|
|
288
|
+
```go
|
|
289
|
+
import "github.com/felixge/fgtrace"
|
|
290
|
+
|
|
291
|
+
// Enable in development only (causes stop-the-world pauses)
|
|
292
|
+
func init() {
|
|
293
|
+
if os.Getenv("ENV") == "dev" {
|
|
294
|
+
fgtrace.Start()
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### pprof - Standard Go Profiler
|
|
300
|
+
|
|
301
|
+
Built into Kratos HTTP server:
|
|
302
|
+
|
|
303
|
+
```go
|
|
304
|
+
import "net/http/pprof"
|
|
305
|
+
|
|
306
|
+
// Automatically available at /debug/pprof/
|
|
307
|
+
// - /debug/pprof/heap - memory profile
|
|
308
|
+
// - /debug/pprof/goroutine - goroutine profile
|
|
309
|
+
// - /debug/pprof/profile?seconds=30 - CPU profile
|
|
310
|
+
// - /debug/pprof/trace - execution trace
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
---
|
|
314
|
+
|
|
315
|
+
## Common Error Patterns
|
|
316
|
+
|
|
317
|
+
### Error Creation
|
|
318
|
+
|
|
319
|
+
```go
|
|
320
|
+
import "github.com/go-kratos/kratos/v2/errors"
|
|
321
|
+
|
|
322
|
+
// Standard errors
|
|
323
|
+
var ErrUserNotFound = errors.NotFound("USER_NOT_FOUND", "user not found")
|
|
324
|
+
|
|
325
|
+
// With details
|
|
326
|
+
func (uc *UserUseCase) GetUser(ctx context.Context, id string) (*User, error) {
|
|
327
|
+
user, err := uc.repo.FindByID(ctx, id)
|
|
328
|
+
if err != nil {
|
|
329
|
+
return nil, errors.NotFound("USER_NOT_FOUND", "user %s not found", id)
|
|
330
|
+
}
|
|
331
|
+
return user, nil
|
|
332
|
+
}
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### Error Response Format
|
|
336
|
+
|
|
337
|
+
```json
|
|
338
|
+
{
|
|
339
|
+
"code": 404,
|
|
340
|
+
"reason": "USER_NOT_FOUND",
|
|
341
|
+
"message": "user 123 not found",
|
|
342
|
+
"metadata": {
|
|
343
|
+
"user_id": "123"
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
### Error Checking
|
|
349
|
+
|
|
350
|
+
```go
|
|
351
|
+
// Check error type
|
|
352
|
+
if errors.Is(err, v1.ErrUserNotFound) {
|
|
353
|
+
// Handle user not found
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// Check error code
|
|
357
|
+
if se := errors.FromError(err); se.Code == 404 {
|
|
358
|
+
// Handle not found
|
|
359
|
+
}
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
---
|
|
363
|
+
|
|
364
|
+
## gRPC Error Mapping
|
|
365
|
+
|
|
366
|
+
Kratos HTTP gateway maps HTTP status to gRPC status:
|
|
367
|
+
|
|
368
|
+
| HTTP Status | gRPC Status |
|
|
369
|
+
|-------------|-------------|
|
|
370
|
+
| 400 | InvalidArgument |
|
|
371
|
+
| 401 | Unauthenticated |
|
|
372
|
+
| 403 | PermissionDenied |
|
|
373
|
+
| 404 | NotFound |
|
|
374
|
+
| 409 | AlreadyExists |
|
|
375
|
+
| 500 | Internal |
|
|
376
|
+
| 503 | Unavailable |
|
|
377
|
+
|
|
378
|
+
```go
|
|
379
|
+
// Create HTTP-compatible error
|
|
380
|
+
errors.BadRequest("INVALID_PARAM", "invalid parameter")
|
|
381
|
+
// → HTTP 400, gRPC InvalidArgument
|
|
382
|
+
|
|
383
|
+
errors.Unauthenticated("TOKEN_EXPIRED", "token expired")
|
|
384
|
+
// → HTTP 401, gRPC Unauthenticated
|
|
385
|
+
```
|
|
@@ -29,6 +29,7 @@ By default, `plan` includes the full consensus review loop formerly documented u
|
|
|
29
29
|
- Default planning is consensus-first, not lightweight-by-default.
|
|
30
30
|
- Treat the clarify spec as source of truth; do not re-interview unless the spec is incomplete or contradictory.
|
|
31
31
|
- Keep planning artifact-bound: produce PRD, architecture, development plan, and test plan outputs.
|
|
32
|
+
- Preserve accepted intent as durable change artifacts: proposal, spec delta, design, tasks, and artifact dependency graph.
|
|
32
33
|
- Separate planning approval from execution approval.
|
|
33
34
|
- Do not start implementation from `plan`.
|
|
34
35
|
- Prefer a smaller executable plan over a broad plan that cannot be verified.
|
|
@@ -59,8 +60,8 @@ If no requirements artifact is provided, derive a task slug and run pre-context
|
|
|
59
60
|
Before planning:
|
|
60
61
|
|
|
61
62
|
1. Derive a task slug.
|
|
62
|
-
2. Reuse the latest relevant `.
|
|
63
|
-
3. If none exists, create `.
|
|
63
|
+
2. Reuse the latest relevant `.loopx/context/{slug}-*.md` snapshot when available.
|
|
64
|
+
3. If none exists, create `.loopx/context/{slug}-{timestamp}.md` with:
|
|
64
65
|
- task statement
|
|
65
66
|
- desired outcome
|
|
66
67
|
- source requirements artifact
|
|
@@ -130,6 +131,7 @@ Critic evaluates:
|
|
|
130
131
|
- clarity of risk mitigation
|
|
131
132
|
- testable acceptance criteria
|
|
132
133
|
- concrete verification steps
|
|
134
|
+
- execution-input completeness for each new or changed ingress / workflow entrypoint
|
|
133
135
|
- explicit non-goals and decision boundaries
|
|
134
136
|
- in deliberate mode: pre-mortem and expanded test plan quality
|
|
135
137
|
|
|
@@ -161,11 +163,20 @@ On approval, write canonical planning artifacts:
|
|
|
161
163
|
- `.loopx/workflows/<slug>/test-plan.md`
|
|
162
164
|
- `.loopx/plans/prd-<slug>.md`
|
|
163
165
|
- `.loopx/plans/test-spec-<slug>.md`
|
|
166
|
+
- `.loopx/changes/active/<change-id>/proposal.md`
|
|
167
|
+
- `.loopx/changes/active/<change-id>/spec-delta.md`
|
|
168
|
+
- `.loopx/changes/active/<change-id>/design.md`
|
|
169
|
+
- `.loopx/changes/active/<change-id>/tasks.md`
|
|
170
|
+
- `.loopx/changes/active/<change-id>/slices.json`
|
|
171
|
+
- `.loopx/changes/active/<change-id>/artifact-graph.json`
|
|
164
172
|
|
|
165
173
|
The final plan must include:
|
|
166
174
|
|
|
167
175
|
- ADR: Decision, Drivers, Alternatives considered, Why chosen, Consequences, Follow-ups
|
|
168
176
|
- concrete implementation steps sized to the actual task
|
|
177
|
+
- target long-lived spec domains and the requirements delta for archive
|
|
178
|
+
- vertical slices sized as independently verifiable tracer bullets, not horizontal layer-only task groups
|
|
179
|
+
- execution inputs mapped to concrete sources before build starts
|
|
169
180
|
- available execution lanes and recommended lane
|
|
170
181
|
- test and verification commands
|
|
171
182
|
- residual risks and assumptions
|
|
@@ -197,17 +208,25 @@ Without `--interactive`, report the approved plan and recommended next command,
|
|
|
197
208
|
- `plan_architect_review_status`: `not-started|complete|changes-requested`
|
|
198
209
|
- `plan_critic_verdict`: `none|approve|iterate|reject`
|
|
199
210
|
- `plan_package_status`: `missing|partial|complete`
|
|
211
|
+
- `change_artifacts_status`: `missing|partial|complete|archived`
|
|
212
|
+
- `spec_delta_status`: `missing|partial|complete`
|
|
213
|
+
- `slice_artifacts_status`: `missing|partial|complete`
|
|
200
214
|
- `plan_acceptance_criteria_testable`: `true|false`
|
|
201
215
|
- `plan_verification_steps_resolved`: `true|false`
|
|
216
|
+
- `plan_execution_inputs_resolved`: `true|false`
|
|
202
217
|
- `requested_transition`: remains explicit before build/autopilot
|
|
203
218
|
|
|
204
219
|
The plan gate is blocked until:
|
|
205
220
|
|
|
206
221
|
- plan package artifacts exist
|
|
222
|
+
- change proposal, spec delta, design, tasks, vertical slices, and artifact graph exist
|
|
223
|
+
- spec delta declares target domains and added or modified requirements
|
|
224
|
+
- vertical slices contain at least one `AFK` or `HITL` end-to-end slice with acceptance criteria and verification signal
|
|
207
225
|
- Architect review is complete
|
|
208
226
|
- Critic verdict is `approve`
|
|
209
227
|
- acceptance criteria are testable
|
|
210
228
|
- verification steps are concrete
|
|
229
|
+
- execution inputs are fully mapped to concrete sources
|
|
211
230
|
- user approval exists for any execution transition
|
|
212
231
|
</Runtime_State_Machine>
|
|
213
232
|
|
|
@@ -225,6 +244,7 @@ Primary outputs:
|
|
|
225
244
|
|
|
226
245
|
- approved plan package under `.loopx/workflows/<slug>/`
|
|
227
246
|
- canonical PRD and test spec under `.loopx/plans/`
|
|
247
|
+
- change artifacts under `.loopx/changes/active/<change-id>/`
|
|
228
248
|
- consensus review summary with Planner / Architect / Critic evidence
|
|
229
249
|
- next-step recommendation
|
|
230
250
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: review
|
|
3
3
|
description: Repo-local acceptance surface for loopx.
|
|
4
|
+
argument-hint: "<execution-record path or workflow slug>"
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
# loopx Review
|
|
@@ -9,21 +10,117 @@ description: Repo-local acceptance surface for loopx.
|
|
|
9
10
|
|
|
10
11
|
Repo-local acceptance surface for loopx. Use it to evaluate the execution package from `build` and return an explicit go / no-go result.
|
|
11
12
|
|
|
13
|
+
## Inputs
|
|
14
|
+
|
|
15
|
+
Preferred skill input:
|
|
16
|
+
|
|
17
|
+
- `.loopx/workflows/<slug>/execution-record.md`
|
|
18
|
+
|
|
19
|
+
Compatible skill / CLI input:
|
|
20
|
+
|
|
21
|
+
- `<slug>`
|
|
22
|
+
|
|
23
|
+
When invoked with an execution record path, derive `<slug>` from the workflow directory and evaluate the matching active run.
|
|
24
|
+
|
|
12
25
|
## Expected Outputs
|
|
13
26
|
|
|
14
27
|
- a review artifact tied to the run being evaluated
|
|
15
28
|
- verdict and rationale
|
|
16
|
-
-
|
|
29
|
+
- code review findings for the implementation diff, including file / line references when issues are found
|
|
30
|
+
- architecture-smell findings from the internal review lane, focused on module depth, test seams, domain vocabulary, duplicated rules, and plan architecture alignment
|
|
31
|
+
- rollback/fix guidance when execution is incomplete, unstable, or needs another iteration
|
|
32
|
+
- an explicit `Next:` block with the exact next skill command when more work remains
|
|
33
|
+
|
|
34
|
+
## User Notification Language
|
|
35
|
+
|
|
36
|
+
The final user-facing review result must be written in Chinese.
|
|
37
|
+
|
|
38
|
+
Use stable machine values only where they are commands, file paths, JSON/state fields, or exact verdict identifiers. The human-readable summary, rationale, findings, residual risks, rollback guidance, and next-step instruction must be Chinese.
|
|
17
39
|
|
|
18
40
|
## Decision Boundary
|
|
19
41
|
|
|
20
42
|
- Use this only after build has produced execution and verification evidence for a specific run.
|
|
21
43
|
- Stop here if review evidence is incomplete. `review` remains an independent gate and does not auto-complete the workflow.
|
|
44
|
+
- Review must include code review of the build-owned implementation diff. Do not limit review to artifact/schema checks.
|
|
45
|
+
- Review must include the architecture-smell lane as part of review evidence. This is not a new workflow stage and must not create extra user steps.
|
|
46
|
+
- Review must compare the execution scope against the approved workflow scope. If `execution-record.md` declares non-empty `remaining_scope`, `completion_claim` other than `full`, or a mismatch between `planned_scope` and `implemented_scope`, review must return no-go and route to build or plan. A partial slice may be accepted as useful work, but it must not be approved as full workflow completion.
|
|
47
|
+
- Code review findings should focus on real bugs, regressions, missing tests, broken contracts, security/data-integrity risks, and user-visible behavior gaps.
|
|
48
|
+
- If code review finds blocking high or medium severity issues, return a no-go verdict and rollback guidance instead of approving completion.
|
|
49
|
+
- If architecture-smell findings are only advisory, record them as warnings without blocking. Block only when module seams, testability, domain boundaries, duplicated rules, or plan architecture assumptions are materially wrong.
|
|
50
|
+
- Route request-changes by problem type:
|
|
51
|
+
- implementation bugs, missing tests, small contract fixes: `review -> build`
|
|
52
|
+
- wrong plan, wrong architecture, unresolved execution inputs: `review -> plan`
|
|
53
|
+
- unclear product requirements or decision boundaries: `review -> clarify`
|
|
54
|
+
- Do not route implementation-only fixes back to plan unless the plan itself is wrong.
|
|
55
|
+
|
|
56
|
+
## Next Step Format
|
|
57
|
+
|
|
58
|
+
Every no-go review result must end with a concrete next command block.
|
|
59
|
+
|
|
60
|
+
For implementation fixes:
|
|
61
|
+
|
|
62
|
+
```text
|
|
63
|
+
Next:
|
|
64
|
+
$build --from-review .loopx/workflows/<slug>/review-report.md
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The review artifact is the direct rework contract for implementation fixes. `$build --from-review ...` must load the review findings first, while still using the approved PRD, test spec, previous `execution-record.md`, and workflow-local plan package as supporting context. Do not make the normal Codex-facing handoff require a separate bash `loopx approve ... --from review --to build` step.
|
|
68
|
+
|
|
69
|
+
For CLI/runtime debugging only, the equivalent state transition is:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
loopx build --from-review .loopx/workflows/<slug>/review-report.md
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
For plan fixes:
|
|
76
|
+
|
|
77
|
+
```text
|
|
78
|
+
Next:
|
|
79
|
+
loopx approve <slug> --from review --to plan
|
|
80
|
+
$plan <slug>
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
For clarify fixes:
|
|
84
|
+
|
|
85
|
+
```text
|
|
86
|
+
Next:
|
|
87
|
+
loopx approve <slug> --from review --to clarify
|
|
88
|
+
$clarify <slug>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
For approval:
|
|
92
|
+
|
|
93
|
+
```text
|
|
94
|
+
Next:
|
|
95
|
+
loopx approve <slug> --from review --to done
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
After the workflow reaches `done`, run:
|
|
99
|
+
|
|
100
|
+
```text
|
|
101
|
+
$archive <slug>
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
This syncs the approved `.loopx/changes/active/<change-id>/spec-delta.md` into long-lived `.loopx/specs/` files and moves the change folder under `.loopx/changes/archive/<change-id>/`.
|
|
105
|
+
|
|
106
|
+
## Support Skill Review Lenses
|
|
107
|
+
|
|
108
|
+
Use loopx support skills as review lenses, not as implementation instructions:
|
|
109
|
+
|
|
110
|
+
- `verify`: Evidence lens. Reject completion, passing, or review-ready claims that lack fresh command output and exit status.
|
|
111
|
+
- `scope`: Completion lens. Reject full-completion claims when the execution record still declares remaining workflow scope or only a partial slice was implemented.
|
|
112
|
+
- `tdd`: Behavior-change lens. Feature work and bug fixes should include failing-test or regression-test evidence unless the execution record explicitly explains why tests are not applicable.
|
|
113
|
+
- `debug`: Failure-analysis lens. Fixes for bugs, test failures, build failures, and unexpected behavior should document root cause, not only symptoms or attempted patches.
|
|
114
|
+
- `go-style`: Go diff lens. For `.go` changes, review happy-path structure, error handling, context usage, interface boundaries, naming, table tests, and `gofmt`/Go verification evidence.
|
|
115
|
+
- `kratos`: Kratos diff lens. For Kratos/proto/service/biz/data/middleware/auth/config changes, review layer boundaries, generated-code flow, proto/package contracts, middleware/auth ordering, config compatibility, and project-native verification.
|
|
116
|
+
|
|
117
|
+
These lenses can produce review findings when the execution package violates them. Do not run new build work from `review`; request rollback or changes instead.
|
|
22
118
|
|
|
23
119
|
## Must Not Decide Automatically
|
|
24
120
|
|
|
25
121
|
- final completion without an explicit approval step
|
|
26
122
|
- re-running build work inside the review surface
|
|
123
|
+
- editing code or rerunning build from inside review
|
|
27
124
|
|
|
28
125
|
## Notes
|
|
29
126
|
|