@educa-corp/sdd-framework 0.6.0 → 0.7.0
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/bin/gate-trace.js +25 -2
- package/bin/index.js +32 -5
- package/bin/lint-trace.js +41 -0
- package/bin/self-check.js +430 -3
- package/bin/trace-schema.json +391 -30
- package/core/FRAMEWORK_VERSION +1 -1
- package/{commands/extend-prd.md → core/commands/amend-prd.md} +205 -173
- package/core/commands/dev-run-test.md +47 -9
- package/core/commands/extend-prd.md +39 -12
- package/core/commands/generate-bdd.md +43 -4
- package/core/commands/generate-code.md +33 -0
- package/core/commands/generate-tech-docs.md +34 -2
- package/core/commands/qc-run-test.md +29 -3
- package/core/commands/refine-prd.md +13 -2
- package/core/commands/review-context.md +43 -8
- package/core/commands/sync.md +105 -1
- package/core/commands/validate-traces.md +284 -11
- package/core/rules/workflow.md +34 -0
- package/core/steps/context-loader.md +26 -5
- package/core/templates/feature.template +1 -1
- package/docs/02-concepts/architecture.md +36 -0
- package/docs/04-reference/commands.md +148 -134
- package/docs/04-reference/trace-schema.md +39 -0
- package/docs/explain/02b-extend-prd.md +1 -1
- package/docs/explain/02c-amend-prd.md +152 -0
- package/docs/explain/28-sync.md +25 -0
- package/docs/explain/README.md +136 -135
- package/package.json +1 -8
- package/commands/debug.md +0 -529
- package/commands/debug.tmpl +0 -260
- package/commands/define-product.md +0 -438
- package/commands/define-product.tmpl +0 -225
- package/commands/dev-gen-test.md +0 -700
- package/commands/dev-gen-test.tmpl +0 -490
- package/commands/dev-run-test.md +0 -435
- package/commands/dev-run-test.tmpl +0 -225
- package/commands/dev-smoke-test.md +0 -374
- package/commands/dev-smoke-test.tmpl +0 -217
- package/commands/extend-prd.tmpl +0 -273
- package/commands/fix-bug.md +0 -519
- package/commands/fix-bug.tmpl +0 -197
- package/commands/generate-architecture.md +0 -354
- package/commands/generate-architecture.tmpl +0 -197
- package/commands/generate-bdd.md +0 -923
- package/commands/generate-bdd.tmpl +0 -590
- package/commands/generate-code.md +0 -859
- package/commands/generate-code.tmpl +0 -649
- package/commands/generate-design-spec.md +0 -737
- package/commands/generate-design-spec.tmpl +0 -524
- package/commands/generate-prd.md +0 -722
- package/commands/generate-prd.tmpl +0 -226
- package/commands/generate-spec-manifest.md +0 -321
- package/commands/generate-spec-manifest.tmpl +0 -164
- package/commands/generate-tech-docs.md +0 -920
- package/commands/generate-tech-docs.tmpl +0 -273
- package/commands/learn.md +0 -399
- package/commands/learn.tmpl +0 -130
- package/commands/map-testids.md +0 -238
- package/commands/map-testids.tmpl +0 -81
- package/commands/propose-scenario.md +0 -359
- package/commands/propose-scenario.tmpl +0 -202
- package/commands/qc-analyze.md +0 -269
- package/commands/qc-analyze.tmpl +0 -112
- package/commands/qc-design-test.md +0 -226
- package/commands/qc-design-test.tmpl +0 -69
- package/commands/qc-plan.md +0 -206
- package/commands/qc-plan.tmpl +0 -49
- package/commands/qc-report.md +0 -217
- package/commands/qc-report.tmpl +0 -60
- package/commands/qc-review.md +0 -210
- package/commands/qc-review.tmpl +0 -53
- package/commands/qc-run-test.md +0 -326
- package/commands/qc-run-test.tmpl +0 -116
- package/commands/refine-prd.md +0 -653
- package/commands/refine-prd.tmpl +0 -281
- package/commands/report-bug.md +0 -305
- package/commands/report-bug.tmpl +0 -148
- package/commands/review-code.md +0 -415
- package/commands/review-code.tmpl +0 -146
- package/commands/review-context.md +0 -902
- package/commands/review-context.tmpl +0 -530
- package/commands/review-tech-docs.md +0 -561
- package/commands/review-tech-docs.tmpl +0 -404
- package/commands/setup-ai-first.md +0 -602
- package/commands/setup-ai-first.tmpl +0 -450
- package/commands/sync.md +0 -430
- package/commands/sync.tmpl +0 -429
- package/commands/update-framework.md +0 -203
- package/commands/update-framework.tmpl +0 -202
- package/commands/validate-traces.md +0 -1077
- package/commands/validate-traces.tmpl +0 -920
- package/hooks/data-guard.js +0 -232
- package/hooks/settings.json +0 -19
- package/modules/android-compose/module.yaml +0 -13
- package/modules/android-compose/stack-profile.yaml +0 -57
- package/modules/angular/architecture-snippets/component-patterns.md +0 -187
- package/modules/angular/module.yaml +0 -6
- package/modules/angular/stack-profile.yaml +0 -38
- package/modules/context-engineering/architecture-snippets/context-design.md +0 -119
- package/modules/context-engineering/module.yaml +0 -9
- package/modules/context-engineering/stack-profile.yaml +0 -61
- package/modules/dotnet/architecture-snippets/clean-arch.md +0 -160
- package/modules/dotnet/module.yaml +0 -6
- package/modules/dotnet/stack-profile.yaml +0 -50
- package/modules/flutter/module.yaml +0 -14
- package/modules/flutter/stack-profile.yaml +0 -59
- package/modules/golang/architecture-snippets/domain-layout.md +0 -283
- package/modules/golang/module.yaml +0 -6
- package/modules/golang/stack-profile.yaml +0 -40
- package/modules/ios-swiftui/module.yaml +0 -13
- package/modules/ios-swiftui/stack-profile.yaml +0 -55
- package/modules/java-spring/architecture-snippets/layered-arch.md +0 -201
- package/modules/java-spring/module.yaml +0 -15
- package/modules/java-spring/stack-profile.yaml +0 -28
- package/modules/nextjs/architecture-snippets/app-router-patterns.md +0 -269
- package/modules/nextjs/module.yaml +0 -14
- package/modules/nextjs/stack-profile.yaml +0 -74
- package/modules/nuxt/module.yaml +0 -14
- package/modules/nuxt/stack-profile.yaml +0 -58
- package/modules/phaser-game/architecture-snippets/phaser-scene-patterns.md +0 -646
- package/modules/phaser-game/module.yaml +0 -15
- package/modules/phaser-game/stack-profile.yaml +0 -90
- package/modules/php-laravel/architecture-snippets/service-repository.md +0 -302
- package/modules/php-laravel/module.yaml +0 -15
- package/modules/php-laravel/stack-profile.yaml +0 -56
- package/modules/qc-playwright/stack-profile.yaml +0 -66
- package/modules/react/architecture-snippets/hooks-query-patterns.md +0 -254
- package/modules/react/module.yaml +0 -14
- package/modules/react/stack-profile.yaml +0 -63
- package/modules/react-native/module.yaml +0 -14
- package/modules/react-native/stack-profile.yaml +0 -56
- package/modules/vue/module.yaml +0 -14
- package/modules/vue/stack-profile.yaml +0 -65
- package/rules/data-protection.md +0 -80
- package/rules/workflow.md +0 -99
- package/skills/code/SKILL.md +0 -19
- package/skills/code/SKILL.tmpl +0 -19
- package/skills/debug/SKILL.md +0 -19
- package/skills/debug/SKILL.tmpl +0 -19
- package/skills/design-spec/SKILL.md +0 -11
- package/skills/design-spec/SKILL.tmpl +0 -11
- package/skills/discovery/SKILL.md +0 -14
- package/skills/discovery/SKILL.tmpl +0 -14
- package/skills/prd/SKILL.md +0 -19
- package/skills/prd/SKILL.tmpl +0 -19
- package/skills/qc/qa-analyst/DOC_GAPS.template.md +0 -63
- package/skills/qc/qa-analyst/acceptance-criteria.md +0 -60
- package/skills/qc/qa-analyst/business-rules.md +0 -59
- package/skills/qc/qa-analyst/data-flow.md +0 -64
- package/skills/qc/qa-analyst/spec-breakdown.md +0 -61
- package/skills/qc/qa-designer/e2e/journey.md +0 -41
- package/skills/qc/qa-designer/exploratory/charter.md +0 -68
- package/skills/qc/qa-designer/exploratory/explore-to-functional.md +0 -43
- package/skills/qc/qa-designer/functional/api.md +0 -45
- package/skills/qc/qa-designer/functional/gui-feature.md +0 -46
- package/skills/qc/qa-designer/functional/gui-screen.md +0 -52
- package/skills/qc/qa-designer/integration/api.md +0 -42
- package/skills/qc/qa-designer/integration/db.md +0 -39
- package/skills/qc/qa-designer/integration/gui.md +0 -40
- package/skills/qc/qa-designer/integration/kafka.md +0 -40
- package/skills/qc/qa-designer/non-functional.md +0 -40
- package/skills/qc/qa-planner/test-plan.md +0 -120
- package/skills/qc/qa-reviewer/script/e2e.md +0 -87
- package/skills/qc/qa-reviewer/script/exploratory.md +0 -45
- package/skills/qc/qa-reviewer/script/functional.md +0 -101
- package/skills/qc/qa-reviewer/script/integration.md +0 -91
- package/skills/qc/qa-reviewer/script/non-functional.md +0 -126
- package/skills/qc/qa-reviewer/test-case/e2e.md +0 -73
- package/skills/qc/qa-reviewer/test-case/exploratory.md +0 -43
- package/skills/qc/qa-reviewer/test-case/functional.md +0 -76
- package/skills/qc/qa-reviewer/test-case/integration.md +0 -69
- package/skills/qc/qa-reviewer/test-case/non-functional.md +0 -73
- package/skills/qc/qa-runner/e2e.md +0 -49
- package/skills/qc/qa-runner/exploratory/session.md +0 -36
- package/skills/qc/qa-runner/functional/api.md +0 -35
- package/skills/qc/qa-runner/functional/gui-feature.md +0 -51
- package/skills/qc/qa-runner/functional/gui-screen.md +0 -55
- package/skills/qc/qa-runner/integration.md +0 -47
- package/skills/qc/qa-runner/non-functional.md +0 -49
- package/skills/qc/qa-runner/report/report.md +0 -37
- package/skills/setup-ai-first/SKILL.md +0 -19
- package/skills/setup-ai-first/SKILL.tmpl +0 -19
- package/skills/spec/SKILL.md +0 -19
- package/skills/spec/SKILL.tmpl +0 -19
- package/skills/test/SKILL.md +0 -18
- package/skills/test/SKILL.tmpl +0 -18
- package/steps/business-language.md +0 -56
- package/steps/capture-lesson.md +0 -112
- package/steps/context-loader.md +0 -406
- package/steps/gate.md +0 -151
- package/steps/report-footer.md +0 -125
- package/steps/review-fanout.md +0 -159
- package/steps/spawn-agent.md +0 -129
- package/steps/trace-mirror.md +0 -53
- package/templates/README.md +0 -70
- package/templates/architecture.template.md +0 -394
- package/templates/ci/trace-gate.yml +0 -146
- package/templates/design-spec.template.md +0 -217
- package/templates/feature.template +0 -123
- package/templates/hooks/pre-push +0 -61
- package/templates/platform-guide.template.md +0 -145
- package/templates/prd.template.md +0 -283
- package/templates/product-definition.template.md +0 -188
- package/templates/project-context.yaml +0 -212
- package/templates/tech-design.template.md +0 -490
package/bin/trace-schema.json
CHANGED
|
@@ -937,17 +937,37 @@
|
|
|
937
937
|
"Đội/submodule sở hữu scenario. Nguồn: @trace.service của header .feature.",
|
|
938
938
|
"VÌ SAO TỒN TẠI (G31): validate-traces Step 0 và trace-mirror.md đều khẳng định trace gộp",
|
|
939
939
|
"'không cần tách theo service vì mỗi row mang @trace.service' — nhưng TSV KHÔNG có cột nào",
|
|
940
|
-
"cho nó và JSON report cũng không.
|
|
941
|
-
"
|
|
942
|
-
"
|
|
943
|
-
"
|
|
944
|
-
"
|
|
940
|
+
"cho nó và JSON report cũng không. Cột này làm lời khẳng định kia thành sự thật.",
|
|
941
|
+
"",
|
|
942
|
+
"BỐN GIÁ TRỊ — G51 tách hai cái từng bị gộp:",
|
|
943
|
+
" {path} = đã route xong, đây là repo sở hữu",
|
|
944
|
+
" unrouted = CHƯA AI QUYẾT repo. Trạng thái HỢP LỆ và BÌNH THƯỜNG ở feature đầu tiên của",
|
|
945
|
+
" một domain mới. Cờ 🟠 SERVICE_UNROUTED. KHÔNG chặn BDD, KHÔNG chặn PR.",
|
|
946
|
+
" unresolved = CONFIG SAI CẤU TRÚC (một entry vừa có path vừa có by_prd_slug, hoặc",
|
|
947
|
+
" by_prd_slug lồng nhau). Đây là BUG cần sửa file, không phải trạng thái chờ.",
|
|
948
|
+
" '—' = single-service mode, không có khái niệm service",
|
|
949
|
+
"",
|
|
950
|
+
"VÌ SAO PHẢI TÁCH (G51): trước đó 'unresolved' mang CẢ HAI nghĩa nên cả hai chịu chung một",
|
|
951
|
+
"hình phạt — /generate-bdd DỪNG HẲN. Nhưng PRD/BDD là artifact NGHIỆP VỤ: PO biết domain",
|
|
952
|
+
"(auth, payment) và biết platform (web/app — người dùng làm việc đó ở đâu), nhưng KHÔNG biết",
|
|
953
|
+
"code sẽ nằm repo nào, và thường lúc đó CHƯA AI QUYẾT. Nên cổng đặt sai phase: nó chặn phase",
|
|
954
|
+
"KHÔNG CẦN biết, còn generate-code — phase BUỘC PHẢI biết mới ghi được file — thì không kiểm.",
|
|
955
|
+
"Ca bị đánh nặng nhất là feature ĐẦU TIÊN của một domain mới: chưa có mapping ⇒ PO bị chặn",
|
|
956
|
+
"bởi một quyết định thuộc architect, ở phase architect còn chưa vào.",
|
|
957
|
+
"",
|
|
958
|
+
"AI PHÂN GIẢI: validate-traces đọc lại services: mỗi lần chạy và nâng unrouted → path khi",
|
|
959
|
+
"mapping xuất hiện — giống cách nó đã làm với spec_ver. Architect thêm mapping ⇒ sổ TỰ LÀNH,",
|
|
960
|
+
"không sửa tay, KHÔNG phải chạy lại /generate-bdd. Vì thế validate-traces là producer thứ hai",
|
|
961
|
+
"của cột này, và đó là ngoại lệ CÓ CHỦ Ý với luật 'mỗi cột một chủ': nó không ghi giá trị mới,",
|
|
962
|
+
"nó chỉ phân giải một placeholder mà generate-bdd đã cố ý để lại."
|
|
945
963
|
],
|
|
946
964
|
"written_by": [
|
|
947
|
-
"generate-bdd"
|
|
965
|
+
"generate-bdd",
|
|
966
|
+
"validate-traces"
|
|
948
967
|
],
|
|
949
968
|
"read_by": [
|
|
950
|
-
"validate-traces"
|
|
969
|
+
"validate-traces",
|
|
970
|
+
"generate-code"
|
|
951
971
|
]
|
|
952
972
|
},
|
|
953
973
|
{
|
|
@@ -1154,6 +1174,7 @@
|
|
|
1154
1174
|
"audit_flags": {
|
|
1155
1175
|
"$lint": "n/a — không sống trong TSV. Cờ audit được tính lúc chạy và sống trong trace-report.json (issues + summary counter); R7 canh đủ ba tầng của chúng. lint-trace chỉ kiểm file trên đĩa, nên không có gì để neo.",
|
|
1156
1176
|
"values": [
|
|
1177
|
+
"PRD_UNTRACKED_EDIT",
|
|
1157
1178
|
"PRD_DRIFT",
|
|
1158
1179
|
"PRD_STALE_REF",
|
|
1159
1180
|
"BDD_DRIFT",
|
|
@@ -1167,7 +1188,8 @@
|
|
|
1167
1188
|
"SEAM_UNWIRED",
|
|
1168
1189
|
"STUB_UNRESOLVED",
|
|
1169
1190
|
"SEAM_PENDING",
|
|
1170
|
-
"STUB_PENDING"
|
|
1191
|
+
"STUB_PENDING",
|
|
1192
|
+
"SERVICE_UNROUTED"
|
|
1171
1193
|
]
|
|
1172
1194
|
}
|
|
1173
1195
|
},
|
|
@@ -1245,17 +1267,48 @@
|
|
|
1245
1267
|
],
|
|
1246
1268
|
"label_marker": "Checkpoint:",
|
|
1247
1269
|
"hard": [
|
|
1248
|
-
{
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1270
|
+
{
|
|
1271
|
+
"cmd": "generate-prd",
|
|
1272
|
+
"why": "ghi đè PRD đã có → mất changelog, ĐÁNH SỐ LẠI BR, phá @trace.business_rules trong mọi .feature đã sinh"
|
|
1273
|
+
},
|
|
1274
|
+
{
|
|
1275
|
+
"cmd": "extend-prd",
|
|
1276
|
+
"why": "sửa PRD đã DUYỆT"
|
|
1277
|
+
},
|
|
1278
|
+
{
|
|
1279
|
+
"cmd": "amend-prd",
|
|
1280
|
+
"why": "SỬA TẠI CHỖ một AC/BR/UC đã duyệt — thao tác ghi DUY NHẤT trong framework được phép làm output KHÔNG phải superset của bản cũ"
|
|
1281
|
+
},
|
|
1282
|
+
{
|
|
1283
|
+
"cmd": "refine-prd",
|
|
1284
|
+
"why": "--resume áp findings trực tiếp vào PRD"
|
|
1285
|
+
},
|
|
1286
|
+
{
|
|
1287
|
+
"cmd": "generate-architecture",
|
|
1288
|
+
"why": "ghi đè architecture.md đã verified_by một người thật"
|
|
1289
|
+
}
|
|
1252
1290
|
],
|
|
1253
1291
|
"none": [
|
|
1254
|
-
{
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
{
|
|
1292
|
+
{
|
|
1293
|
+
"cmd": "review-code",
|
|
1294
|
+
"why": "read-only"
|
|
1295
|
+
},
|
|
1296
|
+
{
|
|
1297
|
+
"cmd": "validate-traces",
|
|
1298
|
+
"why": "read-only (ghi trace-report.json + TSV status, không đụng spec/code)"
|
|
1299
|
+
},
|
|
1300
|
+
{
|
|
1301
|
+
"cmd": "debug",
|
|
1302
|
+
"why": "read-only"
|
|
1303
|
+
},
|
|
1304
|
+
{
|
|
1305
|
+
"cmd": "review-context",
|
|
1306
|
+
"why": "read-only (ghi findings vào .agent/review/)"
|
|
1307
|
+
},
|
|
1308
|
+
{
|
|
1309
|
+
"cmd": "review-tech-docs",
|
|
1310
|
+
"why": "read-only (ghi findings vào .agent/review/)"
|
|
1311
|
+
}
|
|
1259
1312
|
]
|
|
1260
1313
|
},
|
|
1261
1314
|
"audit_invalidating_tags": {
|
|
@@ -1292,38 +1345,150 @@
|
|
|
1292
1345
|
],
|
|
1293
1346
|
"ci_template": "templates/ci/trace-gate.yml",
|
|
1294
1347
|
"tags": [
|
|
1295
|
-
{
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1348
|
+
{
|
|
1349
|
+
"tag": "@trace.implements",
|
|
1350
|
+
"flags": [
|
|
1351
|
+
"ORPHANED",
|
|
1352
|
+
"TRACE_ORPHAN"
|
|
1353
|
+
]
|
|
1354
|
+
},
|
|
1355
|
+
{
|
|
1356
|
+
"tag": "@trace.verifies",
|
|
1357
|
+
"flags": [
|
|
1358
|
+
"ORPHANED",
|
|
1359
|
+
"TRACE_ORPHAN"
|
|
1360
|
+
]
|
|
1361
|
+
},
|
|
1362
|
+
{
|
|
1363
|
+
"tag": "@trace.seam_port",
|
|
1364
|
+
"flags": [
|
|
1365
|
+
"SEAM_UNWIRED"
|
|
1366
|
+
]
|
|
1367
|
+
},
|
|
1368
|
+
{
|
|
1369
|
+
"tag": "@trace.seam_pending",
|
|
1370
|
+
"flags": [
|
|
1371
|
+
"SEAM_UNWIRED"
|
|
1372
|
+
]
|
|
1373
|
+
},
|
|
1374
|
+
{
|
|
1375
|
+
"tag": "@trace.stub",
|
|
1376
|
+
"flags": [
|
|
1377
|
+
"STUB_UNRESOLVED"
|
|
1378
|
+
]
|
|
1379
|
+
},
|
|
1380
|
+
{
|
|
1381
|
+
"tag": "@trace.stub_owner",
|
|
1382
|
+
"flags": [
|
|
1383
|
+
"STUB_UNRESOLVED"
|
|
1384
|
+
]
|
|
1385
|
+
},
|
|
1386
|
+
{
|
|
1387
|
+
"tag": "@trace.stub_for",
|
|
1388
|
+
"flags": [
|
|
1389
|
+
"STUB_UNRESOLVED"
|
|
1390
|
+
]
|
|
1391
|
+
}
|
|
1302
1392
|
]
|
|
1303
1393
|
},
|
|
1394
|
+
"report_root_keys": {
|
|
1395
|
+
"$comment": [
|
|
1396
|
+
"KEY Ở CẤP GỐC CỦA trace-report.json MÀ gate-trace ĐỌC (G57).",
|
|
1397
|
+
"",
|
|
1398
|
+
"VÌ SAO KHỐI NÀY TỒN TẠI: `report.domain` từng có 1 consumer (gate-trace, và nó CHẶN PR nếu",
|
|
1399
|
+
"giá trị khác 'all') và 0 producer — validate-traces không có cờ nào để đặt nó. Năm chỗ trong",
|
|
1400
|
+
"lệnh mô tả một 'domain argument' / 'domain filter' KHÔNG TỒN TẠI: ghi chú Gate ('target là",
|
|
1401
|
+
"một tên domain hoặc UC-ID cụ thể từ $ARGUMENTS') · Step 1 đọc TSV 'khớp domain target' ·",
|
|
1402
|
+
"schema report '<domain argument, or all if no filter>' · Step 8 'nếu có domain filter, chỉ",
|
|
1403
|
+
"gồm các PRD đó trong prds[]' · dòng trace-history mang field domain.",
|
|
1404
|
+
"Nên ô đó LUÔN ghi 'all', và phần kiểm của gate CHƯA BAO GIỜ chạy một lần nào.",
|
|
1405
|
+
"",
|
|
1406
|
+
"Đây ĐÚNG hình dạng R1 fail build vì nó ('field có consumer mà không có producer' — ca",
|
|
1407
|
+
"@trace.sc_version: 3 consumer, 0 producer, sống qua nhiều version không ai bắt được). Nó sống",
|
|
1408
|
+
"được vì R1 chỉ canh field trong SỔ TSV và tag trong CODE — không rule nào canh key ở cấp gốc",
|
|
1409
|
+
"của BIÊN BẢN JSON. Cùng điểm mù mà R13 vừa bịt cho `spec_baseline`.",
|
|
1410
|
+
"",
|
|
1411
|
+
"Và ghi chú Gate còn tệ hơn im lặng: một agent đọc 'target là một tên domain hoặc UC-ID' sẽ",
|
|
1412
|
+
"TIN rằng scoping hoạt động.",
|
|
1413
|
+
"",
|
|
1414
|
+
"R9(h) là phần 'máy canh': mỗi key phải CÓ MẶT trong skeleton JSON của validate-traces VÀ được",
|
|
1415
|
+
"gate-trace đọc qua `report.{key}`. Cả hai đầu, không đầu nào được lửng."
|
|
1416
|
+
],
|
|
1417
|
+
"keys": [
|
|
1418
|
+
{
|
|
1419
|
+
"key": "scope",
|
|
1420
|
+
"shape": "{ kind: all | domain | prd | uc, value: string }",
|
|
1421
|
+
"written_by": "validate-traces",
|
|
1422
|
+
"read_by": "gate-trace",
|
|
1423
|
+
"why": "Gate PHẢI chặn mọi biên bản phiến diện, không chỉ biên bản hẹp-theo-domain — xem $comment của scope_kinds cho ca false-green mà `domain` một mình không bắt được."
|
|
1424
|
+
},
|
|
1425
|
+
{
|
|
1426
|
+
"key": "domain",
|
|
1427
|
+
"shape": "tên domain, hoặc 'all'",
|
|
1428
|
+
"written_by": "validate-traces",
|
|
1429
|
+
"read_by": "gate-trace",
|
|
1430
|
+
"why": "Giữ cho TƯƠNG THÍCH NGƯỢC: biên bản sinh trước G57 không có `scope`. Gate rơi về logic cũ + in ⚠️ 'kiểm độ phủ đang ở mức yếu' thay vì fail — người dùng chưa chạy lại /validate-traces không phải là lỗi của họ. Cùng khuôn backward-compat G48 đã dùng cho `platform`."
|
|
1431
|
+
}
|
|
1432
|
+
],
|
|
1433
|
+
"scope_kinds": {
|
|
1434
|
+
"$comment": [
|
|
1435
|
+
"BẪY FALSE-GREEN mà bản fix G57 sẽ TỰ TAY MỞ nếu không siết G2 cùng lúc.",
|
|
1436
|
+
"",
|
|
1437
|
+
"gate-trace bản cũ: `if (domain !== 'all') { others = domainsOnDisk().filter(≠domain);",
|
|
1438
|
+
"if (others.length) fail }`. Trong repo MỘT domain, `others` là RỖNG ⇒ KHÔNG fail. Nên một",
|
|
1439
|
+
"biên bản hẹp-theo-PRD (hoặc hẹp-theo-UC) trong repo một domain sẽ được gate nhận là 'toàn",
|
|
1440
|
+
"bộ' — đúng cái 'cấp giấy xanh cho thứ chưa ai xem' mà chú thích của chính nó cảnh báo.",
|
|
1441
|
+
"",
|
|
1442
|
+
"Hiện tại vô hại vì không ai scope được. Nó BẬT NGAY khi scoping thành khả dụng. Nên điều",
|
|
1443
|
+
"kiện đúng là: `scope.kind !== 'all'` ⇒ FAIL, KHÔNG ngoại lệ — không phụ thuộc vào việc trên",
|
|
1444
|
+
"đĩa có bao nhiêu domain.",
|
|
1445
|
+
"",
|
|
1446
|
+
"Thêm cờ scope mà không siết G2 là biến cổng thành SÂN KHẤU — đúng cái G39 dựng lên để chống."
|
|
1447
|
+
],
|
|
1448
|
+
"values": ["all", "domain", "prd", "uc"],
|
|
1449
|
+
"gate_rule": "scope.kind !== 'all' ⇒ FAIL G2, không ngoại lệ",
|
|
1450
|
+
"flags": [
|
|
1451
|
+
{ "flag": "--domain", "kind": "domain", "arg": "{domain}" },
|
|
1452
|
+
{ "flag": "--prd", "kind": "prd", "arg": "{TICKET-ID}" },
|
|
1453
|
+
{ "flag": "--uc", "kind": "uc", "arg": "{UC-ID}" }
|
|
1454
|
+
]
|
|
1455
|
+
}
|
|
1456
|
+
},
|
|
1304
1457
|
"blocking": [
|
|
1305
1458
|
{
|
|
1306
1459
|
"counter": "orphaned_count",
|
|
1307
1460
|
"issues_key": "orphaned",
|
|
1308
|
-
"label_fields": [
|
|
1461
|
+
"label_fields": [
|
|
1462
|
+
"sc_id",
|
|
1463
|
+
"platform"
|
|
1464
|
+
],
|
|
1309
1465
|
"why": "code + test còn trỏ vào scenario đã bị xoá khỏi .feature"
|
|
1310
1466
|
},
|
|
1311
1467
|
{
|
|
1312
1468
|
"counter": "trace_orphan_count",
|
|
1313
1469
|
"issues_key": "trace_orphan",
|
|
1314
|
-
"label_fields": [
|
|
1470
|
+
"label_fields": [
|
|
1471
|
+
"sc_id",
|
|
1472
|
+
"file"
|
|
1473
|
+
],
|
|
1315
1474
|
"why": "tag trong code trỏ vào SC-ID không tồn tại — không chỗ nào khác bắt được"
|
|
1316
1475
|
},
|
|
1317
1476
|
{
|
|
1318
1477
|
"counter": "seam_unwired_count",
|
|
1319
1478
|
"issues_key": "seam_unwired",
|
|
1320
|
-
"label_fields": [
|
|
1479
|
+
"label_fields": [
|
|
1480
|
+
"port",
|
|
1481
|
+
"consumer_uc"
|
|
1482
|
+
],
|
|
1321
1483
|
"why": "luồng ghép đang chạy vào stub thay vì hàng thật"
|
|
1322
1484
|
},
|
|
1323
1485
|
{
|
|
1324
1486
|
"counter": "stub_unresolved_count",
|
|
1325
1487
|
"issues_key": "stub_unresolved",
|
|
1326
|
-
"label_fields": [
|
|
1488
|
+
"label_fields": [
|
|
1489
|
+
"artifact",
|
|
1490
|
+
"consumer_uc"
|
|
1491
|
+
],
|
|
1327
1492
|
"why": "hàm rỗng chưa được lấp, nhưng caller đã gọi"
|
|
1328
1493
|
}
|
|
1329
1494
|
],
|
|
@@ -1339,7 +1504,9 @@
|
|
|
1339
1504
|
"soft = lệch thì WARN (phụ thuộc quy ước đếm — vd ORPHANED được report biểu diễn bằng",
|
|
1340
1505
|
"boolean `orphaned` chứ không phải giá trị `status`, nên không ép cứng)."
|
|
1341
1506
|
],
|
|
1342
|
-
"hard": {
|
|
1507
|
+
"hard": {
|
|
1508
|
+
"total_scs": "số row dữ liệu trong mọi TSV thuộc phạm vi report"
|
|
1509
|
+
},
|
|
1343
1510
|
"soft": {
|
|
1344
1511
|
"drift_count": "DRIFT",
|
|
1345
1512
|
"gap_count": "GAP",
|
|
@@ -1363,13 +1530,207 @@
|
|
|
1363
1530
|
"so tổng số + in ⚠️ 'kiểm độ tươi đang ở mức yếu', KHÔNG fail — người dùng chưa chạy",
|
|
1364
1531
|
"lại /validate-traces không phải là lỗi của họ."
|
|
1365
1532
|
],
|
|
1366
|
-
"key_fields": [
|
|
1533
|
+
"key_fields": [
|
|
1534
|
+
"sc_id",
|
|
1535
|
+
"platform"
|
|
1536
|
+
],
|
|
1367
1537
|
"compare": "status",
|
|
1368
1538
|
"orphaned_flag": "orphaned",
|
|
1369
1539
|
"orphaned_status": "ORPHANED"
|
|
1370
1540
|
}
|
|
1371
1541
|
}
|
|
1372
1542
|
},
|
|
1543
|
+
"changelog_row_contract": {
|
|
1544
|
+
"$comment": [
|
|
1545
|
+
"DÒNG CHANGELOG LÀ CONTRACT MÁY ĐỌC (G52 · G53 · G58).",
|
|
1546
|
+
"",
|
|
1547
|
+
"PRD phủ nhiều UC nhưng `Version` là MỘT scalar; tech-doc gộp cấp PRD phủ nhiều UC",
|
|
1548
|
+
"nhưng `@trace.revision` cũng là một scalar. Nên sửa một UC làm MỌI UC lệch version.",
|
|
1549
|
+
"Bộ lọc ở validate-traces Step 4/5 chống báo động oan bằng cách đọc dòng changelog để",
|
|
1550
|
+
"biết lần bump đó ĐỤNG UC NÀO — nên dòng đó không phải văn xuôi cho người đọc, nó là",
|
|
1551
|
+
"ĐẦU VÀO của một phép phân loại 🟠-vs-ⓘ.",
|
|
1552
|
+
"",
|
|
1553
|
+
"VÌ SAO CẦN KHỐI NÀY: trước đó contract này là contract DUY NHẤT có consumer ĐƯỢC CANH",
|
|
1554
|
+
"(R1–R11 canh tên cột/field) mà KHÔNG producer nào được canh. Bốn lệnh ghi nó, ba hình",
|
|
1555
|
+
"dạng khác nhau, không ai kiểm — và hỏng theo CẢ HAI hướng:",
|
|
1556
|
+
" G52 /review-context --fix ghi `Auto-fix: applied {N} findings` — 0 scope ⇒ 🟠 cho MỌI",
|
|
1557
|
+
" UC. Lệnh chạy thường xuyên nhất trong lane PO là lệnh gây nhiễu nhất; sau vài",
|
|
1558
|
+
" sprint PRD_DRIFT sáng thường trực và không ai đọc nữa — mất luôn cờ đúng.",
|
|
1559
|
+
" G53 /extend-prd ghi `sửa BR8` — nêu BR mà KHÔNG nêu UC sở hữu ⇒ UC đổi thật bị xếp ⓘ",
|
|
1560
|
+
" ⇒ rào của `--realign-prd-version` (chỉ chặn 🟠) MỞ CỬA ⇒ nhãn version bị dán lại",
|
|
1561
|
+
" trên một BR vừa đổi hành vi. Đây là hướng IM LẶNG, nặng hơn hướng ỒN.",
|
|
1562
|
+
" G58 /generate-tech-docs chỉ nói `thêm một row Changelog` — không format, không ví dụ.",
|
|
1563
|
+
" Chưa nổ vì comment trong template tình cờ đúng. Nợ chờ lệch.",
|
|
1564
|
+
"",
|
|
1565
|
+
"LỜI GIẢI ĐÃ TỒN TẠI TRONG CHÍNH FRAMEWORK: nhánh BDD của review-context Fix Mode",
|
|
1566
|
+
"Phase 3 làm đúng chuẩn — bump `sc_version` theo TỪNG scenario bị đụng, liệt kê check",
|
|
1567
|
+
"nào đổi thân scenario, và nói thẳng lý do (`bump vô cớ tạo DRIFT giả và làm cờ mất giá",
|
|
1568
|
+
"trị`). Nhánh PRD ngay trên nó thì không. Khối này chỉ nâng cách làm đó lên thành",
|
|
1569
|
+
"contract cho cả bốn producer.",
|
|
1570
|
+
"",
|
|
1571
|
+
"self-check R12 là phần `máy canh`: producer phải nhắc `scope_token`, consumer phải",
|
|
1572
|
+
"nhắc `scope_token` + `neutral_marker` + `resolve_to_uc.anchor`. Marker được GHI mà",
|
|
1573
|
+
"consumer không HIỂU thì tệ hơn không có marker — nó bị coi là văn xuôi và lọt im lặng."
|
|
1574
|
+
],
|
|
1575
|
+
"scope_token": "{changelog_scope}",
|
|
1576
|
+
"scope_grammar": "Mỗi mệnh đề mở đầu bằng ĐƠN VỊ SỞ HỮU rồi tới mô tả: `{UC-ID}: {mô tả}`. Nhiều mệnh đề ngăn bằng `;`. Nội dung không thuộc UC nào → `PRD-global: {mô tả}`. BR/AC luôn đi KÈM UC sở hữu (`UC3: sửa BR8`) và KHÔNG BAO GIỜ đứng một mình (`sửa BR8`) — consumer khớp theo UC, nên một BR đứng một mình làm UC sở hữu nó bị xếp ⓘ trong khi nội dung của nó vừa đổi.",
|
|
1577
|
+
"ambiguous_fallback": "Không mệnh đề nào nêu được đơn vị sở hữu → consumer coi row là MƠ HỒ và gắn 🟠 cho MỌI UC (lưới an toàn: không suy đoán được thì quét rộng). Đây là hành vi ĐÚNG khi thiếu thông tin — nhưng là hành vi SAI khi producer CÓ thông tin mà không ghi.",
|
|
1578
|
+
"neutral_marker": "[no-behavior]",
|
|
1579
|
+
"neutral_semantics": "Hậu tố đặt sau một mệnh đề mà producer CHỨNG MINH ĐƯỢC là không đổi hành vi. Consumer: UC nêu trong mệnh đề có marker này KHÔNG bị 🟠 — nó ở lại ⓘ. Chỉ producer nào biết chính xác loại fix mình vừa áp mới được dùng; KHÔNG dùng cho người tự khai.",
|
|
1580
|
+
"neutral_checks": [
|
|
1581
|
+
{ "check": "P4:skeleton", "why": "thêm section/metadata skeleton còn THIẾU — cấu trúc, không có nội dung nghiệp vụ nào mới" },
|
|
1582
|
+
{ "check": "P4:status-row", "why": "thêm `| **Status** | draft |` khi row vắng — giá trị mặc định, không phải quyết định nghiệp vụ" },
|
|
1583
|
+
{ "check": "P4:drop-empty-api-section", "why": "xoá section `Existing API Contract` RỖNG ở greenfield — xoá chỗ trống" }
|
|
1584
|
+
],
|
|
1585
|
+
"not_neutral_checks": [
|
|
1586
|
+
{ "check": "P1:banned-term", "why": "term đó cũng nằm trong .feature đã sinh — BDD lỗi thời THẬT về thuật ngữ (B2/C4 sẽ bắt). Đổi từ trong PRD mà không nêu UC là bỏ sót, không phải trung tính." },
|
|
1587
|
+
{ "check": "P1:tech-jargon", "why": "auto-fix của nó là `diễn đạt lại` / `chuyển Design Spec` / `bỏ về Tech Docs` — VIẾT LẠI câu văn AC/BR, và nhánh 2/3 LẤY nội dung ra khỏi PRD. Không chứng minh được là trung tính." }
|
|
1588
|
+
],
|
|
1589
|
+
"resolve_to_uc": {
|
|
1590
|
+
"required": true,
|
|
1591
|
+
"anchor": "BR/AC → UC sở hữu",
|
|
1592
|
+
"how": "Chuẩn hoá tập bị ảnh hưởng VỀ UC trước khi so: BR → UC có BR đó trong bảng Business Rule (PRD §3); AC → UC có AC đó ở dòng `**AC liên quan:**`. Không có bước này thì phép thử `UC này có trong tập?` luôn FALSE cho một row chỉ nêu BR/AC ⇒ ⓘ sai (G53). Step 4 đã mở file PRD nên không phát sinh I/O.",
|
|
1593
|
+
"fallback": "BR/AC không phân giải được về UC nào (ID đã bị xoá, hoặc PRD lệch cấu trúc) → coi row là MƠ HỒ (🟠 cho mọi UC), KHÔNG bỏ qua mệnh đề đó."
|
|
1594
|
+
},
|
|
1595
|
+
"producers": [
|
|
1596
|
+
{ "cmd": "refine-prd", "artifact": "PRD", "where": "Phase 3", "scope_source": "`uc_id` / `section` của các finding được chấp nhận" },
|
|
1597
|
+
{ "cmd": "extend-prd", "artifact": "PRD", "where": "Bước 6", "scope_source": "UC mới + UC SỞ HỮU mỗi BR/AC bị sửa (kết luận của Bước 3.2)" },
|
|
1598
|
+
{ "cmd": "amend-prd", "artifact": "PRD", "where": "Bước 5", "scope_source": "UC SỞ HỮU của mỗi ID mà PO khai tường minh ở Bước 1 (`amend_targets`)" },
|
|
1599
|
+
{ "cmd": "review-context", "artifact": "PRD", "where": "Fix Mode Phase 3", "scope_source": "`uc_id` của mọi finding `status: applied` (findings YAML — field bắt buộc)", "emits_neutral_marker": true, "why_emits": "nó là producer DUY NHẤT biết chính xác `check_id` của từng fix vừa áp, nên là producer duy nhất chứng minh được tính trung tính" },
|
|
1600
|
+
{ "cmd": "generate-tech-docs", "artifact": "tech-design.md", "where": "Bước 1 (APPEND) + §Sinh", "scope_source": "UC trong `input_features` của batch vừa thêm/sửa" }
|
|
1601
|
+
],
|
|
1602
|
+
"consumers": [
|
|
1603
|
+
{ "cmd": "validate-traces", "where": "Step 4 (PRD) · Step 5 (tech-doc)", "use": "phân loại 🟠 DRIFT vs ⓘ STALE_REF theo từng UC" },
|
|
1604
|
+
{ "cmd": "generate-bdd", "where": "Version Check", "use": "khuyến nghị Y (cập nhật hẹp) vs F (gen lại toàn bộ)" }
|
|
1605
|
+
]
|
|
1606
|
+
},
|
|
1607
|
+
"spec_edit_detection": {
|
|
1608
|
+
"$comment": [
|
|
1609
|
+
"PHÁT HIỆN SỬA TÀI LIỆU NGOÀI ĐƯỜNG CHÍNH THỨC (G54, nửa sau).",
|
|
1610
|
+
"",
|
|
1611
|
+
"TOÀN BỘ lưới an toàn của framework so NHÃN VERSION, không so NỘI DUNG — không có một",
|
|
1612
|
+
"content hash nào ở đâu. Nên một PRD bị sửa tay mà không bump version là điểm mù TUYỆT",
|
|
1613
|
+
"ĐỐI: validate-traces thấy `PRD version == prd_version` ⇒ sạch · gate-trace thấy report",
|
|
1614
|
+
"khớp sổ ⇒ PASS · require-fresh-audit thấy PR không chạm tag ⇒ không đòi audit. Cả ba",
|
|
1615
|
+
"tầng xanh, và cả ba ĐÚNG theo định nghĩa của chính chúng.",
|
|
1616
|
+
"",
|
|
1617
|
+
"Và G54 không chỉ CHO PHÉP sửa tay — nó ĐẨY người dùng về đó: /generate-prd chỉ có một",
|
|
1618
|
+
"cổng chặn-cứng rồi vẫn ghi đè (mất changelog, đánh số lại BR) · /extend-prd chỉ",
|
|
1619
|
+
"add-only · /refine-prd chỉ áp được finding do chính nó tìm ra. Trước /amend-prd, hành",
|
|
1620
|
+
"vi hợp lý duy nhất còn lại LÀ mở file .md ra gõ. Thiết kế tự tạo ra con đường nó không",
|
|
1621
|
+
"canh được.",
|
|
1622
|
+
"",
|
|
1623
|
+
"VÌ SAO KHÔNG DÙNG CONTENT HASH: git đã băm nội dung hộ rồi. Thêm một cột hash vào sổ",
|
|
1624
|
+
"TSV là thêm một thứ ghi-tay-bởi-LLM (đúng lớp lỗi G38 mà lint-trace tồn tại để chống),",
|
|
1625
|
+
"trong khi `git diff` trả lời chính xác cùng câu hỏi và không sai được.",
|
|
1626
|
+
"",
|
|
1627
|
+
"VÌ SAO KHÔNG NẰM TRONG `gate.blocking` — quyết định có chủ ý, không phải bỏ sót:",
|
|
1628
|
+
" 1. `gate.blocking` có nghĩa HẸP là CODE ĐANG HỎNG, và R9(e) tồn tại để giữ ranh giới",
|
|
1629
|
+
" đó. Cờ này nói về SPEC; code có thể đang hoàn toàn đúng.",
|
|
1630
|
+
" 2. Nợ tồn khi mới bật: mọi project đang chạy đều đã có PRD sửa tay. Một cờ chặn mới",
|
|
1631
|
+
" sẽ đỏ khắp nơi ở lần chạy đầu ⇒ người ta TẮT CỔNG ⇒ mất luôn 4 cờ 🔴 thật. Đó",
|
|
1632
|
+
" đúng là thất bại R9(e) được viết ra để chặn, chỉ đến bằng một cửa khác.",
|
|
1633
|
+
" 3. Nó vẫn 🔴 trong REPORT và in mỗi lần chạy — đủ để thấy, không đủ để làm tắt cổng.",
|
|
1634
|
+
"Team nào đã dọn sạch nợ tồn thì tự thêm counter này vào `gate.blocking`; một dòng.",
|
|
1635
|
+
"",
|
|
1636
|
+
"ĐƯỜNG RA TỰ LÀNH — cố ý KHÔNG có lệnh escape riêng: cách sửa đúng là bump version +",
|
|
1637
|
+
"ghi một row changelog (tức chính việc /amend-prd làm hộ). Làm xong thì",
|
|
1638
|
+
"`version != version_at_audit` ⇒ cờ tự tắt, và logic PRD_DRIFT bình thường tiếp quản.",
|
|
1639
|
+
"Thêm một `--accept-edit` sẽ là thêm một đường DÁN NHÃN lên thay đổi chưa ai xem — đúng",
|
|
1640
|
+
"cái sai mà rào của `--realign` tồn tại để chặn."
|
|
1641
|
+
],
|
|
1642
|
+
"flag": "PRD_UNTRACKED_EDIT",
|
|
1643
|
+
"detects": "nội dung file PRD đã đổi kể từ lần audit trước NHƯNG nhãn `Version` không đổi ⇒ có người sửa ngoài /generate-prd · /extend-prd · /amend-prd · /refine-prd · /review-context",
|
|
1644
|
+
"baseline_fields": {
|
|
1645
|
+
"$comment": "validate-traces GHI khối này vào trace-report.json mỗi lần chạy; lần chạy sau ĐỌC nó làm mốc. Thiếu nửa GHI thì cờ không bao giờ bật — R6/R7 chỉ canh được nửa BÁO CÁO (giá trị enum có xuất hiện · counter có trong summary), nên self-check R13 canh nửa này.",
|
|
1646
|
+
"path": "spec_baseline",
|
|
1647
|
+
"keys": ["prd_path", "sha_at_audit", "version_at_audit"]
|
|
1648
|
+
},
|
|
1649
|
+
"evidence": [
|
|
1650
|
+
{ "source": "git diff", "cmd": "git -C {specs repo} diff --name-only {sha_at_audit}..HEAD -- {prd_path}", "catches": "sửa đã commit" },
|
|
1651
|
+
{ "source": "git status", "cmd": "git -C {specs repo} status --porcelain -- {prd_path}", "catches": "sửa CHƯA commit — ca thường gặp nhất khi PO đang gõ" }
|
|
1652
|
+
],
|
|
1653
|
+
"no_false_positive": "PO sửa VÀ bump version → `version != version_at_audit` → KHÔNG bật cờ. Chỉ đúng ca \"đổi nội dung, giữ nguyên nhãn\" mới bật.",
|
|
1654
|
+
"degraded": "Không phải git repo, hoặc `sha_at_audit` không còn (history bị rewrite) → BỎ QUA check này và in một dòng ⚠️ nói rõ là đang mù, KHÔNG bịa cờ và KHÔNG im lặng.",
|
|
1655
|
+
"written_by": ["validate-traces"],
|
|
1656
|
+
"read_by": ["validate-traces", "sync"],
|
|
1657
|
+
"$read_by_comment": [
|
|
1658
|
+
"`sync` đọc mốc này để trả lời câu KHÁC với câu của diff pull-to-pull (G56).",
|
|
1659
|
+
"Diff `{old_sha}..{new_sha}` trả lời \"đổi gì kể từ lần PULL trước\" — mốc đó RESET mỗi lần",
|
|
1660
|
+
"pull. Pull thứ Hai, thứ Ba, thứ Tư mà không audit lần nào thì đến thứ Năm cái thấy được chỉ",
|
|
1661
|
+
"là delta của MỘT ngày, không phải nợ đã tích. `sha_at_audit` trả lời \"đổi gì kể từ lần",
|
|
1662
|
+
"AUDIT gần nhất\" — con số đó tích luỹ đúng, không bao giờ reset sai."
|
|
1663
|
+
]
|
|
1664
|
+
},
|
|
1665
|
+
"positive_assertion_guards": {
|
|
1666
|
+
"$comment": [
|
|
1667
|
+
"QUYỀN ĐƯỢC KHẲNG ĐỊNH `pass` (G55) — mệnh đề ĐỐI NGẪU của luật G28.",
|
|
1668
|
+
"",
|
|
1669
|
+
"rules/workflow.md §\"Làm mất hiệu lực ≠ ghi đè\" nói: ai làm một giá trị HẾT ĐÚNG thì BẮT",
|
|
1670
|
+
"BUỘC hạ nó xuống. Luật đó đúng và được thực thi tốt (/generate-bdd, /generate-code,",
|
|
1671
|
+
"/fix-bug đều làm). Nhưng nửa còn lại chưa được viết: AI KHẲNG ĐỊNH MỘT GIÁ TRỊ DƯƠNG THÌ",
|
|
1672
|
+
"PHẢI KIỂM RẰNG MÌNH ĐƯỢC PHÉP KHẲNG ĐỊNH.",
|
|
1673
|
+
"",
|
|
1674
|
+
"Thiếu nửa sau nên chuỗi thành: hạ xuống → dựng lại → hạ xuống → dựng lại.",
|
|
1675
|
+
" 1. PO đổi AC → /generate-bdd đặt status=DRIFT và HẠ dev_selftest→not_run, kèm cảnh báo",
|
|
1676
|
+
" \"{n} test của {sc_id} viết cho spec cũ — /dev-gen-test rà lại trước khi chạy\".",
|
|
1677
|
+
" 2. Sáng sau dev chạy /dev-run-test (thói quen bình thường), CHƯA /generate-code, CHƯA",
|
|
1678
|
+
" /dev-gen-test. Test cũ + code cũ ⇒ xanh hết.",
|
|
1679
|
+
" 3. /dev-run-test ghi dev_selftest=pass, dev_selftest_at=HÔM NAY.",
|
|
1680
|
+
"Row giờ mang status=DRIFT + dev_selftest=pass với ngày hôm nay. Lệnh kế tiếp trong vòng",
|
|
1681
|
+
"lặp dev BÌNH THƯỜNG vừa dựng lại đúng cái tín hiệu /generate-bdd hạ xuống.",
|
|
1682
|
+
"",
|
|
1683
|
+
"VÌ SAO `status` KHÔNG TRỰC GIAO Ở ĐÂY: hai file lệnh viết `dev_selftest`/`qc_status`",
|
|
1684
|
+
"\"trực giao với status\". Trực giao về KẾT QUẢ CHẠY thì đúng. Nhưng ô này không mang nghĩa",
|
|
1685
|
+
"\"test đã chạy và xanh\" — nó mang nghĩa \"scenario này đã được nghiệm thu theo spec HIỆN",
|
|
1686
|
+
"TẠI\". Trên row DRIFT, nghĩa thứ nhất đúng và nghĩa thứ hai SAI. `pass` ở đó không phải",
|
|
1687
|
+
"kết quả sai; nó là lời khẳng định sai về điều mà kết quả đó chứng minh.",
|
|
1688
|
+
"",
|
|
1689
|
+
"TIN XẤU LUÔN HỢP LỆ: `fail` VẪN được ghi trên row DRIFT. Đây là guard cho lời khẳng định",
|
|
1690
|
+
"DƯƠNG, không phải lệnh \"bỏ qua kết quả khi DRIFT\". Test đỏ trên row DRIFT vẫn là thông",
|
|
1691
|
+
"tin thật. Chỉ `pass` cần giấy phép.",
|
|
1692
|
+
"",
|
|
1693
|
+
"VÌ SAO CẦN CẢ HAI TẦNG:",
|
|
1694
|
+
" PA-1 (lệnh đọc status trước khi ghi) chặn NGUỒN.",
|
|
1695
|
+
" PA-2 (lint-trace T12) bắt TRẠNG THÁI, bất kể ai ghi — sổ sửa tay, sổ sinh bởi version",
|
|
1696
|
+
" framework cũ, hay một lệnh tương lai quên luật. T12 rẻ, xác định, chạy được trong",
|
|
1697
|
+
" CI mà không cần LLM.",
|
|
1698
|
+
"T1–T8 kiểm HÌNH DẠNG TỪNG Ô (đủ 24 cột, giá trị trong vocabulary, ngày parse được) —",
|
|
1699
|
+
"không rule nào kiểm NHẤT QUÁN GIỮA CÁC Ô. Nên `status=DRIFT` + `dev_selftest=pass` là một",
|
|
1700
|
+
"sổ HOÀN TOÀN HỢP LỆ với cả 11 rule cũ. T12 là rule đầu tiên nhìn nhiều ô cùng lúc.",
|
|
1701
|
+
"",
|
|
1702
|
+
"LỖ ĐÃ BIẾT, chấp nhận có chủ ý: ca \"spec đổi theo hướng THÊM hành vi mới\". Sau khi",
|
|
1703
|
+
"/generate-code bắt kịp, gen_ver=spec_ver ⇒ status=OK; test cũ vẫn PASS (chúng không sai,",
|
|
1704
|
+
"chỉ KHÔNG PHỦ phần mới); test_count>0 nên không có GAP ⇒ bảng xanh trên một hành vi chưa",
|
|
1705
|
+
"test lần nào. Đóng hẳn ca này cần một cột thứ 25 `test_spec_ver` — đổi contract + lint",
|
|
1706
|
+
"binding + backward-compat với mọi sổ 24 cột đang tồn tại. Hoãn có chủ ý; guard này vẫn",
|
|
1707
|
+
"thu hẹp đáng kể vì trong lúc row còn DRIFT thì dev_selftest bị giữ ở not_run, nên dev",
|
|
1708
|
+
"buộc phải làm gì đó và đường đúng là /dev-gen-test."
|
|
1709
|
+
],
|
|
1710
|
+
"lint_rule": "T12",
|
|
1711
|
+
"blocked_when_status": ["DRIFT", "ORPHANED"],
|
|
1712
|
+
"negative_always_written": "`fail` được ghi bình thường trên MỌI status — guard này chỉ chặn giá trị KHẲNG ĐỊNH. Chặn cả `fail` là biến một guard chống-báo-cáo-sai thành một guard che-tin-xấu.",
|
|
1713
|
+
"guards": [
|
|
1714
|
+
{
|
|
1715
|
+
"column": "dev_selftest",
|
|
1716
|
+
"owner": "dev-run-test",
|
|
1717
|
+
"positive_values": ["pass"],
|
|
1718
|
+
"downgrade_to": "not_run",
|
|
1719
|
+
"companion": "dev_selftest_at",
|
|
1720
|
+
"companion_downgrade": "—",
|
|
1721
|
+
"why": "trên row DRIFT, test cũ đang nghiệm thu một hành vi không còn tồn tại; trên row ORPHANED, scenario đã bị xoá khỏi .feature nên không còn gì để nghiệm thu"
|
|
1722
|
+
},
|
|
1723
|
+
{
|
|
1724
|
+
"column": "qc_status",
|
|
1725
|
+
"owner": "qc-run-test",
|
|
1726
|
+
"positive_values": ["pass"],
|
|
1727
|
+
"downgrade_to": "not_run",
|
|
1728
|
+
"companion": "qc_run_at",
|
|
1729
|
+
"companion_downgrade": "—",
|
|
1730
|
+
"why": "đối xứng hoàn toàn với dev_selftest — `skip` KHÔNG bị chặn vì nó là giá trị trung tính, không phải lời khẳng định"
|
|
1731
|
+
}
|
|
1732
|
+
]
|
|
1733
|
+
},
|
|
1373
1734
|
"path_keys": {
|
|
1374
1735
|
"$comment": "Key phải có trong templates/project-context.yaml VÀ được dùng bởi ít nhất một actor. Key khai mà không ai dùng = key chết (GAPS.md G17).",
|
|
1375
1736
|
"config_file": "templates/project-context.yaml",
|
package/core/FRAMEWORK_VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.7.0
|