@educa-corp/sdd-framework 0.9.2 → 0.9.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.
- package/bin/build.js +11 -0
- package/bin/qc-base-map.json +119 -49
- package/bin/self-check.js +30 -0
- package/core/FRAMEWORK_VERSION +1 -1
- package/core/commands/qc-analyze.md +85 -75
- package/core/commands/qc-design-test.md +144 -25
- package/core/commands/qc-plan.md +40 -7
- package/core/commands/qc-review.md +74 -7
- package/core/commands/qc-run-test.md +21 -1
- package/core/commands/setup-ai-first.md +5 -5
- package/core/commands/update-framework.md +1 -1
- package/core/commands/validate-traces.md +1 -1
- package/core/modules/qc-playwright/stack-profile.yaml +3 -3
- package/core/rules/workflow.md +1 -1
- package/core/skills/qc/qa-analyst/DOC_GAP.template.md +47 -17
- package/core/skills/qc/qa-analyst/acceptance-criteria.md +1 -1
- package/core/skills/qc/qa-analyst/business-rules.md +2 -2
- package/core/skills/qc/qa-analyst/data-flow.md +2 -2
- package/core/skills/qc/qa-analyst/spec-breakdown.md +4 -4
- package/core/skills/qc/qa-analyst/spec-issue-reporter.md +14 -2
- package/core/skills/qc/qa-designer/api/auth-chain.md +155 -0
- package/core/skills/qc/qa-designer/api/auth-sequence.md +75 -0
- package/core/skills/qc/qa-designer/api/common-headers.md +61 -0
- package/core/skills/qc/qa-designer/api/crud-sequence.md +122 -0
- package/core/skills/qc/qa-designer/api/endpoint.md +231 -0
- package/core/skills/qc/qa-designer/api/http-status-codes.md +102 -0
- package/core/skills/qc/qa-designer/e2e/journey.md +13 -8
- package/core/skills/qc/qa-designer/exploratory/charter.md +2 -0
- package/core/skills/qc/qa-designer/exploratory/explore-to-functional.md +7 -4
- package/core/skills/qc/qa-designer/functional/api.md +87 -18
- package/core/skills/qc/qa-designer/functional/gui-feature.md +12 -9
- package/core/skills/qc/qa-designer/functional/gui-screen.md +12 -10
- package/core/skills/qc/qa-designer/integration/api.md +12 -5
- package/core/skills/qc/qa-designer/integration/db.md +12 -6
- package/core/skills/qc/qa-designer/integration/gui.md +12 -5
- package/core/skills/qc/qa-designer/integration/kafka.md +12 -5
- package/core/skills/qc/qa-designer/non-functional.md +12 -5
- package/core/skills/qc/qa-designer/shared/action-keywords-glossary.md +91 -0
- package/core/skills/qc/qa-designer/shared/duplicate-check-procedure.md +105 -0
- package/core/skills/qc/qa-designer/shared/implicit-scenarios.md +22 -0
- package/core/skills/qc/qa-designer/shared/precision-rules.md +198 -0
- package/core/skills/qc/qa-designer/shared/read-doc-gap-inputs.md +25 -0
- package/core/skills/qc/qa-designer/shared/skill-decision-tree.md +93 -0
- package/core/skills/qc/qa-designer/shared/tc-metadata-format.md +243 -0
- package/core/skills/qc/qa-planner/risk-model.md +1 -1
- package/core/skills/qc/qa-planner/test-plan.md +24 -13
- package/core/skills/qc/qa-reviewer/script/e2e.md +9 -1
- package/core/skills/qc/qa-reviewer/script/exploratory.md +9 -1
- package/core/skills/qc/qa-reviewer/script/functional.md +9 -1
- package/core/skills/qc/qa-reviewer/script/integration.md +9 -1
- package/core/skills/qc/qa-reviewer/script/non-functional.md +9 -1
- package/core/skills/qc/qa-reviewer/shared/read-doc-gap-inputs.md +26 -0
- package/core/skills/qc/qa-reviewer/shared/review-check-groups.md +207 -0
- package/core/skills/qc/qa-reviewer/shared/review-file-template.md +228 -0
- package/core/skills/qc/qa-reviewer/test-case/e2e.md +71 -13
- package/core/skills/qc/qa-reviewer/test-case/exploratory.md +53 -4
- package/core/skills/qc/qa-reviewer/test-case/functional.md +63 -15
- package/core/skills/qc/qa-reviewer/test-case/integration.md +64 -12
- package/core/skills/qc/qa-reviewer/test-case/non-functional.md +72 -13
- package/core/skills/qc/qa-runner/e2e.md +1 -1
- package/core/skills/qc/qa-runner/exploratory/session.md +1 -1
- package/core/steps/context-loader.md +1 -1
- package/core/steps/qc-scope.md +119 -0
- package/core/templates/project-context.yaml +3 -1
- package/docs/02-concepts/pipeline-steps/08-qc-automation.md +1 -1
- package/docs/02-concepts/pipeline-steps/09-validate-traces.md +1 -1
- package/docs/04-reference/configuration.md +146 -146
- package/docs/04-reference/trace-schema.md +1 -1
- package/docs/explain/00-setup-ai-first.md +1 -1
- package/docs/explain/15-qc-analyze.md +1 -1
- package/docs/explain/16-qc-plan.md +1 -1
- package/docs/explain/17-qc-design-test.md +1 -1
- package/docs/plans/qc-implementation-log.md +288 -5
- package/docs/plans/qc-sync-command.md +2 -1
- package/package.json +1 -1
- package/scripts/migrate-qc-docs.js +261 -0
package/bin/build.js
CHANGED
|
@@ -56,6 +56,17 @@ const RUNTIME_READ = {
|
|
|
56
56
|
'steps/report-footer.md':
|
|
57
57
|
'**Đọc `.agent/steps/report-footer.md`** và áp đúng khuôn footer trong đó (Status Badge ·\n' +
|
|
58
58
|
'Output Artifacts · Next) cho report cuối, kèm khối bên dưới.',
|
|
59
|
+
|
|
60
|
+
// Vào đây ở B12: nó được 5 lệnh qc-* include, nên inline là nhân 5 bản của cùng một
|
|
61
|
+
// quy trình — đúng loại phình mà test "mức slim" tồn tại để canh (nó bắt được thật).
|
|
62
|
+
'steps/qc-scope.md':
|
|
63
|
+
'**BẮT BUỘC — đọc `.agent/steps/qc-scope.md` và thực thi TOÀN BỘ quy trình trong đó**,\n' +
|
|
64
|
+
'rồi mới tiếp tục phần bên dưới.\n' +
|
|
65
|
+
'\n' +
|
|
66
|
+
'Nó chốt bốn thứ mà mọi trạm QC đều cần: `TICKET-ID` · `active_platform` ·\n' +
|
|
67
|
+
'`qc_artifact_dir` · `uc_list` (kèm trạng thái BDD từng UC, và cờ `--include-draft`).\n' +
|
|
68
|
+
'Bỏ qua thì artifact QC ghi vào **sai thư mục** và `qc_status` ghi vào **sai sổ trace** —\n' +
|
|
69
|
+
'cả hai đều xảy ra trong im lặng, không có bước nào phía sau bắt được.',
|
|
59
70
|
};
|
|
60
71
|
|
|
61
72
|
/**
|
package/bin/qc-base-map.json
CHANGED
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
{
|
|
48
48
|
"upstream": "agents/4-qa-tc-designer.md",
|
|
49
49
|
"targets": [],
|
|
50
|
-
"state": "
|
|
50
|
+
"state": "skipped",
|
|
51
51
|
"why": "dinh nghia agent cua upstream; framework dung command + gate _agent_mode thay cho agent file"
|
|
52
52
|
},
|
|
53
53
|
{
|
|
@@ -329,58 +329,83 @@
|
|
|
329
329
|
},
|
|
330
330
|
{
|
|
331
331
|
"upstream": "skills/qa-tc-designer/api-testcase-designer.md",
|
|
332
|
-
"targets": [
|
|
333
|
-
|
|
332
|
+
"targets": [
|
|
333
|
+
"skills/qc/qa-designer/functional/api.md"
|
|
334
|
+
],
|
|
335
|
+
"state": "ported",
|
|
336
|
+
"base_sha": "211c18728baf029a7572f0ffb161e92a933fa8fb"
|
|
334
337
|
},
|
|
335
338
|
{
|
|
336
339
|
"upstream": "skills/qa-tc-designer/api-testcase-designer/api/flows/auth-sequence.md",
|
|
337
|
-
"targets": [
|
|
338
|
-
|
|
340
|
+
"targets": [
|
|
341
|
+
"skills/qc/qa-designer/api/auth-sequence.md"
|
|
342
|
+
],
|
|
343
|
+
"state": "ported",
|
|
344
|
+
"base_sha": "69d60c12fe6d641638132581cce1dc6c955354a6"
|
|
339
345
|
},
|
|
340
346
|
{
|
|
341
347
|
"upstream": "skills/qa-tc-designer/api-testcase-designer/api/flows/common-flows.md",
|
|
342
348
|
"targets": [],
|
|
343
|
-
"state": "
|
|
349
|
+
"state": "skipped",
|
|
350
|
+
"why": "B12: ban nhap cu, nam gon trong auth-sequence.md + crud-sequence.md (dai va chi tiet hon)."
|
|
344
351
|
},
|
|
345
352
|
{
|
|
346
353
|
"upstream": "skills/qa-tc-designer/api-testcase-designer/api/flows/crud-sequence.md",
|
|
347
|
-
"targets": [
|
|
348
|
-
|
|
354
|
+
"targets": [
|
|
355
|
+
"skills/qc/qa-designer/api/crud-sequence.md"
|
|
356
|
+
],
|
|
357
|
+
"state": "ported",
|
|
358
|
+
"base_sha": "65bf214d9f9beabe3c40b8697ba7c058adfd8bb5"
|
|
349
359
|
},
|
|
350
360
|
{
|
|
351
361
|
"upstream": "skills/qa-tc-designer/api-testcase-designer/api/references/common-headers.md",
|
|
352
|
-
"targets": [
|
|
353
|
-
|
|
362
|
+
"targets": [
|
|
363
|
+
"skills/qc/qa-designer/api/common-headers.md"
|
|
364
|
+
],
|
|
365
|
+
"state": "ported",
|
|
366
|
+
"base_sha": "74f10a36bec7b40f4d9de2d0928798cb6fad0c2c"
|
|
354
367
|
},
|
|
355
368
|
{
|
|
356
369
|
"upstream": "skills/qa-tc-designer/api-testcase-designer/api/references/error-codes.md",
|
|
357
370
|
"targets": [],
|
|
358
|
-
"state": "
|
|
371
|
+
"state": "skipped",
|
|
372
|
+
"why": "B12: ban nhap cu, nam gon trong http-status-codes.md (95 dong, day du hon). Phan header cua no nam trong common-headers.md. Lay ca hai la co hai bang tra cung mot thu roi chung lech nhau."
|
|
359
373
|
},
|
|
360
374
|
{
|
|
361
375
|
"upstream": "skills/qa-tc-designer/api-testcase-designer/api/references/http-status-codes.md",
|
|
362
|
-
"targets": [
|
|
363
|
-
|
|
376
|
+
"targets": [
|
|
377
|
+
"skills/qc/qa-designer/api/http-status-codes.md"
|
|
378
|
+
],
|
|
379
|
+
"state": "ported",
|
|
380
|
+
"base_sha": "a82baa99350f63955245764a6aa57c9dca6d055f"
|
|
364
381
|
},
|
|
365
382
|
{
|
|
366
383
|
"upstream": "skills/qa-tc-designer/api-testcase-designer/api/templates/auth-chain.md",
|
|
367
|
-
"targets": [
|
|
368
|
-
|
|
384
|
+
"targets": [
|
|
385
|
+
"skills/qc/qa-designer/api/auth-chain.md"
|
|
386
|
+
],
|
|
387
|
+
"state": "ported",
|
|
388
|
+
"base_sha": "ef8f9761f1b53d0ccd752f8fe0c13a427fa15f45"
|
|
369
389
|
},
|
|
370
390
|
{
|
|
371
391
|
"upstream": "skills/qa-tc-designer/api-testcase-designer/api/templates/endpoint.md",
|
|
372
|
-
"targets": [
|
|
373
|
-
|
|
392
|
+
"targets": [
|
|
393
|
+
"skills/qc/qa-designer/api/endpoint.md"
|
|
394
|
+
],
|
|
395
|
+
"state": "ported",
|
|
396
|
+
"base_sha": "7b38edd94e5efd37ff561f53cff92adedabaff7f"
|
|
374
397
|
},
|
|
375
398
|
{
|
|
376
399
|
"upstream": "skills/qa-tc-designer/e2e-testcase-designer.md",
|
|
377
400
|
"targets": [],
|
|
378
|
-
"state": "
|
|
401
|
+
"state": "skipped",
|
|
402
|
+
"why": "B12: tuong ung skills/qc/qa-designer/e2e/journey.md. Chua doi chieu noi dung — de danh cho lan ra tang E2E rieng."
|
|
379
403
|
},
|
|
380
404
|
{
|
|
381
405
|
"upstream": "skills/qa-tc-designer/integration-testcase-designer.md",
|
|
382
406
|
"targets": [],
|
|
383
|
-
"state": "
|
|
407
|
+
"state": "skipped",
|
|
408
|
+
"why": "B12: tuong ung 4 skill integration/{api,db,gui,kafka}.md. Chua doi chieu noi dung — de danh."
|
|
384
409
|
},
|
|
385
410
|
{
|
|
386
411
|
"upstream": "skills/qa-tc-designer/manual-excel-testcase.md",
|
|
@@ -391,47 +416,70 @@
|
|
|
391
416
|
{
|
|
392
417
|
"upstream": "skills/qa-tc-designer/nfr-testcase-designer.md",
|
|
393
418
|
"targets": [],
|
|
394
|
-
"state": "
|
|
419
|
+
"state": "skipped",
|
|
420
|
+
"why": "B12: tuong ung skills/qc/qa-designer/non-functional.md. Chua doi chieu noi dung — de danh."
|
|
395
421
|
},
|
|
396
422
|
{
|
|
397
423
|
"upstream": "skills/qa-tc-designer/shared/action-keywords-glossary.md",
|
|
398
|
-
"targets": [
|
|
399
|
-
|
|
424
|
+
"targets": [
|
|
425
|
+
"skills/qc/qa-designer/shared/action-keywords-glossary.md"
|
|
426
|
+
],
|
|
427
|
+
"state": "ported",
|
|
428
|
+
"base_sha": "df56df91eea42342537ccf67b5946df32d98dbf4"
|
|
400
429
|
},
|
|
401
430
|
{
|
|
402
431
|
"upstream": "skills/qa-tc-designer/shared/duplicate-check-procedure.md",
|
|
403
|
-
"targets": [
|
|
404
|
-
|
|
432
|
+
"targets": [
|
|
433
|
+
"skills/qc/qa-designer/shared/duplicate-check-procedure.md"
|
|
434
|
+
],
|
|
435
|
+
"state": "ported",
|
|
436
|
+
"base_sha": "c59357a56b289bb9fb7fae8490db37109209cb3a"
|
|
405
437
|
},
|
|
406
438
|
{
|
|
407
439
|
"upstream": "skills/qa-tc-designer/shared/implicit-scenarios.md",
|
|
408
|
-
"targets": [
|
|
409
|
-
|
|
440
|
+
"targets": [
|
|
441
|
+
"skills/qc/qa-designer/shared/implicit-scenarios.md"
|
|
442
|
+
],
|
|
443
|
+
"state": "ported",
|
|
444
|
+
"base_sha": "6eb801a137ef4dfda97870c1eb36db62f3c782bc"
|
|
410
445
|
},
|
|
411
446
|
{
|
|
412
447
|
"upstream": "skills/qa-tc-designer/shared/precision-rules.md",
|
|
413
|
-
"targets": [
|
|
414
|
-
|
|
448
|
+
"targets": [
|
|
449
|
+
"skills/qc/qa-designer/shared/precision-rules.md"
|
|
450
|
+
],
|
|
451
|
+
"state": "ported",
|
|
452
|
+
"base_sha": "1c2005b55bd94c3e8fa25dfa12a29c8b23f7c01e"
|
|
415
453
|
},
|
|
416
454
|
{
|
|
417
455
|
"upstream": "skills/qa-tc-designer/shared/read-doc-gap-inputs.md",
|
|
418
|
-
"targets": [
|
|
419
|
-
|
|
456
|
+
"targets": [
|
|
457
|
+
"skills/qc/qa-designer/shared/read-doc-gap-inputs.md"
|
|
458
|
+
],
|
|
459
|
+
"state": "ported",
|
|
460
|
+
"base_sha": "a7e113b19f35aa47acf91e55cdfb3f630539806c"
|
|
420
461
|
},
|
|
421
462
|
{
|
|
422
463
|
"upstream": "skills/qa-tc-designer/shared/skill-decision-tree.md",
|
|
423
|
-
"targets": [
|
|
424
|
-
|
|
464
|
+
"targets": [
|
|
465
|
+
"skills/qc/qa-designer/shared/skill-decision-tree.md"
|
|
466
|
+
],
|
|
467
|
+
"state": "ported",
|
|
468
|
+
"base_sha": "57125f0c21512f2abcc55d00420e92c84c95fc8f"
|
|
425
469
|
},
|
|
426
470
|
{
|
|
427
471
|
"upstream": "skills/qa-tc-designer/shared/tc-metadata-format.md",
|
|
428
|
-
"targets": [
|
|
429
|
-
|
|
472
|
+
"targets": [
|
|
473
|
+
"skills/qc/qa-designer/shared/tc-metadata-format.md"
|
|
474
|
+
],
|
|
475
|
+
"state": "ported",
|
|
476
|
+
"base_sha": "a31d66a7a8dab19cf821c9102a88282b09e16cb9"
|
|
430
477
|
},
|
|
431
478
|
{
|
|
432
479
|
"upstream": "skills/qa-tc-designer/ui-testcase-designer.md",
|
|
433
480
|
"targets": [],
|
|
434
|
-
"state": "
|
|
481
|
+
"state": "skipped",
|
|
482
|
+
"why": "B12: framework tach tang UI thanh 3 skill rieng (functional/gui-screen · gui-feature · integration/gui) theo cay quyet dinh, thay vi mot file 341 dong. Ky thuat EP/BVA/Decision-Table/State-Transition da co trong 3 skill do; khuon TC + do chinh xac da tach ra shared/. Con lai la phan khai agent + orchestrator — framework khong co."
|
|
435
483
|
},
|
|
436
484
|
{
|
|
437
485
|
"upstream": "skills/qa-tc-reviewer/api-test-reviewer.md",
|
|
@@ -440,23 +488,35 @@
|
|
|
440
488
|
},
|
|
441
489
|
{
|
|
442
490
|
"upstream": "skills/qa-tc-reviewer/e2e-test-reviewer.md",
|
|
443
|
-
"targets": [
|
|
444
|
-
|
|
491
|
+
"targets": [
|
|
492
|
+
"skills/qc/qa-reviewer/test-case/e2e.md"
|
|
493
|
+
],
|
|
494
|
+
"state": "ported",
|
|
495
|
+
"base_sha": "276d0516f95421c726c8c55dc84c3c9244cf70e1"
|
|
445
496
|
},
|
|
446
497
|
{
|
|
447
498
|
"upstream": "skills/qa-tc-reviewer/exploratory-test-reviewer.md",
|
|
448
|
-
"targets": [
|
|
449
|
-
|
|
499
|
+
"targets": [
|
|
500
|
+
"skills/qc/qa-reviewer/test-case/exploratory.md"
|
|
501
|
+
],
|
|
502
|
+
"state": "ported",
|
|
503
|
+
"base_sha": "4e068bb896739b977a6a5b1f638010d498c46aef"
|
|
450
504
|
},
|
|
451
505
|
{
|
|
452
506
|
"upstream": "skills/qa-tc-reviewer/integration-test-reviewer.md",
|
|
453
|
-
"targets": [
|
|
454
|
-
|
|
507
|
+
"targets": [
|
|
508
|
+
"skills/qc/qa-reviewer/test-case/integration.md"
|
|
509
|
+
],
|
|
510
|
+
"state": "ported",
|
|
511
|
+
"base_sha": "639b54afb68df83b22168581c5c57b0f91d9cf6a"
|
|
455
512
|
},
|
|
456
513
|
{
|
|
457
514
|
"upstream": "skills/qa-tc-reviewer/nfr-test-reviewer.md",
|
|
458
|
-
"targets": [
|
|
459
|
-
|
|
515
|
+
"targets": [
|
|
516
|
+
"skills/qc/qa-reviewer/test-case/non-functional.md"
|
|
517
|
+
],
|
|
518
|
+
"state": "ported",
|
|
519
|
+
"base_sha": "5747c7a6bdfaaea1ff3e958688b38b3aeaf9b15a"
|
|
460
520
|
},
|
|
461
521
|
{
|
|
462
522
|
"upstream": "skills/qa-tc-reviewer/script-e2e-reviewer.md",
|
|
@@ -485,18 +545,28 @@
|
|
|
485
545
|
},
|
|
486
546
|
{
|
|
487
547
|
"upstream": "skills/qa-tc-reviewer/shared/read-doc-gap-inputs.md",
|
|
488
|
-
"targets": [
|
|
489
|
-
|
|
548
|
+
"targets": [
|
|
549
|
+
"skills/qc/qa-reviewer/shared/read-doc-gap-inputs.md"
|
|
550
|
+
],
|
|
551
|
+
"state": "ported",
|
|
552
|
+
"base_sha": "3caa1562399ef1167ac2dc620add2c6c729e55df"
|
|
490
553
|
},
|
|
491
554
|
{
|
|
492
555
|
"upstream": "skills/qa-tc-reviewer/shared/review-file-template.md",
|
|
493
|
-
"targets": [
|
|
494
|
-
|
|
556
|
+
"targets": [
|
|
557
|
+
"skills/qc/qa-reviewer/shared/review-file-template.md"
|
|
558
|
+
],
|
|
559
|
+
"state": "ported",
|
|
560
|
+
"base_sha": "bd596393ecc016cbea106835681a4979c0a9ca0e"
|
|
495
561
|
},
|
|
496
562
|
{
|
|
497
563
|
"upstream": "skills/qa-tc-reviewer/ui-test-reviewer.md",
|
|
498
|
-
"targets": [
|
|
499
|
-
|
|
564
|
+
"targets": [
|
|
565
|
+
"skills/qc/qa-reviewer/test-case/functional.md",
|
|
566
|
+
"skills/qc/qa-reviewer/shared/review-check-groups.md"
|
|
567
|
+
],
|
|
568
|
+
"state": "ported",
|
|
569
|
+
"base_sha": "54f81eb6a132d3fb331f18ce0f1a7eb3a9cf19df"
|
|
500
570
|
}
|
|
501
571
|
],
|
|
502
572
|
"$decisions": {
|
package/bin/self-check.js
CHANGED
|
@@ -1198,6 +1198,12 @@ for (const [vocab, def] of Object.entries(schema.vocabularies)) {
|
|
|
1198
1198
|
// sau đều đoán. Đây đúng loại việc con người không làm đáng tin bằng sự cẩn thận.
|
|
1199
1199
|
// → R16(b).
|
|
1200
1200
|
//
|
|
1201
|
+
// (3) Một file NHẬN nội dung port mà KHÔNG đóng dấu nguồn gốc. Bản đồ khai đầy đủ, sha
|
|
1202
|
+
// đúng, self-check xanh — nhưng người mở file không biết đây là bản port, nên lần
|
|
1203
|
+
// đồng bộ sau bản đồ biết BASE mà người sửa file thì không. Ca thật: B12 gộp nội dung
|
|
1204
|
+
// `api-testcase-designer.md` vào `functional/api.md`. (b) và (e) đều mù vì chúng chỉ
|
|
1205
|
+
// so KHI frontmatter có khai. → R16(f).
|
|
1206
|
+
//
|
|
1201
1207
|
// (a) là cái quan trọng nhất về lâu dài: file upstream KHÔNG có entry trong bản đồ =
|
|
1202
1208
|
// bị bỏ quên trong im lặng. `state: skipped` (có lý do) là câu trả lời hợp lệ; VẮNG MẶT
|
|
1203
1209
|
// thì không. Cùng khuôn với `checkpoint_levels` và `strict_use_check`: khai tường minh
|
|
@@ -1324,6 +1330,30 @@ for (const [vocab, def] of Object.entries(schema.vocabularies)) {
|
|
|
1324
1330
|
}
|
|
1325
1331
|
}
|
|
1326
1332
|
}
|
|
1333
|
+
|
|
1334
|
+
// ── (f) target `ported` phải KHAI dấu nguồn gốc, không chỉ "khai đúng nếu có khai" ──
|
|
1335
|
+
//
|
|
1336
|
+
// Vì sao cần nhánh riêng: (b) và (e) đều chạy trong `if (m)` / `if (mp)` — chúng so
|
|
1337
|
+
// frontmatter với bản đồ KHI frontmatter có khai. File không khai gì thì cả hai im lặng.
|
|
1338
|
+
// Ca thật (B12): `functional/api.md` nhận nội dung port từ `api-testcase-designer.md`,
|
|
1339
|
+
// vào bản đồ đầy đủ với base_sha đúng, self-check XANH — mà đọc file thì không ai biết
|
|
1340
|
+
// nó là bản port. Mất `upstream_path` + `upstream_sha` ở file đích là mất BASE của merge
|
|
1341
|
+
// ba chiều lần sau: bản đồ biết, còn người sửa file thì không.
|
|
1342
|
+
for (const e of entries.filter(x => x.state === 'ported')) {
|
|
1343
|
+
for (const t of (e.targets || [])) {
|
|
1344
|
+
const tp = path.join(ROOT, t);
|
|
1345
|
+
if (!fs.existsSync(tp)) continue; // đã báo ở (c)
|
|
1346
|
+
const txt = fs.readFileSync(tp, 'utf8');
|
|
1347
|
+
const lack = ['upstream_path', 'upstream_sha']
|
|
1348
|
+
.filter(f => !new RegExp(`^${f}: .+$`, 'm').test(txt));
|
|
1349
|
+
if (lack.length) {
|
|
1350
|
+
err('R16', `${t} là target \`ported\` nhưng frontmatter THIẾU ${lack.join(' + ')}`,
|
|
1351
|
+
`Bản đồ khai nó port từ \`${e.upstream}\`, còn chính file thì không đóng dấu.
|
|
1352
|
+
` +
|
|
1353
|
+
' Người mở file không biết đây là bản port, và lần đồng bộ sau mất một chiều BASE.');
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1327
1357
|
}
|
|
1328
1358
|
}
|
|
1329
1359
|
}
|
package/core/FRAMEWORK_VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.9.
|
|
1
|
+
0.9.4
|
|
@@ -165,7 +165,7 @@ Mỗi dòng ⚠️/🔴 phải ứng với một trạng thái **context-loader
|
|
|
165
165
|
🔴/⚠️ (không chặn ≠ không báo — người đọc log sau này vẫn cần thấy).
|
|
166
166
|
|
|
167
167
|
|
|
168
|
-
*Lưu ý: Với lệnh này, target ở Bước 1 là một
|
|
168
|
+
*Lưu ý: Với lệnh này, target ở Bước 1 là một **TICKET-ID** (mã PRD), hoặc một UC-ID / file feature / file PRD — cả ba đều quy về TICKET-ID ở §Phạm vi QC. Trạm này chạy cho **cả PRD × một nền**. Đọc spec chính thức của **mọi UC trong phạm vi** — file `.feature` (mang `@trace.id={UC-ID}` và mỗi scenario `@trace.scenario={UC-ID}-SC{N}`), PRD, và design-spec — từ feature package `{paths.specs_dir}/{domain}/{prd-slug}/` (file `.feature` dưới `bdd/`, file PRD `{TICKET-ID}-{prd-slug}.md` ở gốc folder, và design-spec dưới `design-spec/`). Spec của framework CHÍNH LÀ source of truth; đừng suy lại các requirement đã có ở đó. **Ngoài ra đọc tech-doc gộp** `{paths.tech_docs_dir}/{domain}/{prd-slug}/tech-docs/{TICKET-ID}-tech-design.md` làm **nguồn thứ hai** — xem §Đối chiếu tài liệu kỹ thuật.*
|
|
169
169
|
|
|
170
170
|
## Context
|
|
171
171
|
**BẮT BUỘC — đọc `.agent/steps/context-loader.md` và thực thi TOÀN BỘ quy trình trong đó**,
|
|
@@ -177,60 +177,42 @@ placeholder bên dưới sẽ rỗng và lệnh sẽ đọc/ghi sai chỗ.
|
|
|
177
177
|
|
|
178
178
|
---
|
|
179
179
|
|
|
180
|
-
##
|
|
180
|
+
## Phạm vi QC — PRD nào, nền nào, những UC nào
|
|
181
181
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
> file mang `@trace.status` **riêng**: bản web có thể `approved` trong khi bản app còn `draft`.
|
|
185
|
-
> Guard đọc "file `.feature` của UC" khi chưa biết platform là đọc một file **bất kỳ trong ba**:
|
|
186
|
-
> báo `approved` trong khi bản đang dùng còn nháp, hoặc chặn oan một bản đã duyệt.
|
|
187
|
-
> Chốt platform trước thì Guard mới có đúng một file để đọc.
|
|
188
|
-
|
|
189
|
-
`{UC-ID}-SC{N}` chỉ độc nhất trong (UC × platform) — `web SC3` và `app SC3` là hai scenario khác nhau, và sổ trace tách theo `{UC-ID}-{platform}.tsv`. Nên **một QC pass khoá đúng MỘT platform**, và mọi artifact QC nằm dưới `{paths.qc_dir}/{UC-ID}/{active_platform}/`.
|
|
190
|
-
|
|
191
|
-
Phân giải `active_platform` — theo thứ tự, dừng ở cái đầu tiên khớp:
|
|
192
|
-
1. `$ARGUMENTS` nêu platform (`web`/`app`/`system`) → dùng.
|
|
193
|
-
2. Target ở Bước 1 là một file `.feature` → đọc `# @trace.platform` của nó.
|
|
194
|
-
3. Glob `{paths.specs_dir}/{domain}/{prd-slug}/bdd/*/` — **đúng một** thư mục platform tồn tại → dùng nó.
|
|
195
|
-
4. Nhiều platform mà không suy được → hỏi *"QC pass này cho platform nào? (web/app/system)"*.
|
|
196
|
-
**Có `--yes`:** không hỏi — dừng với lỗi rõ ràng, vì đoán bừa platform là ghi artifact vào sai
|
|
197
|
-
thư mục và ghi `qc_status` vào sai sổ trace:
|
|
198
|
-
```
|
|
199
|
-
❌ {UC-ID} có {n} platform ({list}) — không suy được platform nào cho QC pass này.
|
|
200
|
-
Chạy headless thì phải nêu tường minh: /qc-analyze {UC-ID} web --yes
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
Lưu `active_platform`. Đọc **đúng file `.feature` của platform đó** (`{paths.specs_dir}/{domain}/{prd-slug}/bdd/{active_platform}/{UC-ID}*.feature`) làm nguồn SC — không trộn SC chéo platform.
|
|
204
|
-
|
|
205
|
-
---
|
|
206
|
-
|
|
207
|
-
## Guard — BDD đã duyệt chưa
|
|
182
|
+
**BẮT BUỘC — đọc `.agent/steps/qc-scope.md` và thực thi TOÀN BỘ quy trình trong đó**,
|
|
183
|
+
rồi mới tiếp tục phần bên dưới.
|
|
208
184
|
|
|
209
|
-
|
|
185
|
+
Nó chốt bốn thứ mà mọi trạm QC đều cần: `TICKET-ID` · `active_platform` ·
|
|
186
|
+
`qc_artifact_dir` · `uc_list` (kèm trạng thái BDD từng UC, và cờ `--include-draft`).
|
|
187
|
+
Bỏ qua thì artifact QC ghi vào **sai thư mục** và `qc_status` ghi vào **sai sổ trace** —
|
|
188
|
+
cả hai đều xảy ra trong im lặng, không có bước nào phía sau bắt được.
|
|
210
189
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
⚠️ BDD của {UC-ID} ({active_platform}) đang ở @trace.status: {status} (chưa duyệt). QC chạy trên BDD chưa chốt có thể phải làm lại.
|
|
216
|
-
Khuyến nghị: review-context (BDD) sạch + người duyệt đặt `# @trace.status: approved` rồi mới chạy QC.
|
|
217
|
-
Vẫn chạy QC bây giờ? (Y/N)
|
|
218
|
-
```
|
|
219
|
-
Chỉ tiếp khi chọn Y — **trừ khi `$ARGUMENTS` có `--yes`**: coi như Y, **nhưng vẫn IN khối cảnh
|
|
220
|
-
báo** (không chặn ≠ không báo — người đọc log sau này vẫn cần thấy QC đã chạy trên BDD nháp).
|
|
190
|
+
> **QC chạy trên BDD chưa chốt có thể phải làm lại.** `qc-scope` mặc định chỉ lấy UC có
|
|
191
|
+
> `@trace.status: approved`; UC còn nháp vẫn vào bảng *Phạm vi phân tích* của `DOC_GAP.md`
|
|
192
|
+
> với dấu `⏸ Chưa xét` — **không im lặng bỏ khỏi bảng**, vì "chưa xét" khác "đã xét, sạch".
|
|
193
|
+
> Cố ý QC sớm thì thêm `--include-draft`, và artifact phải ghi rõ nó dựa trên BDD nháp.
|
|
221
194
|
|
|
222
|
-
> **Vì sao
|
|
223
|
-
>
|
|
224
|
-
>
|
|
225
|
-
>
|
|
226
|
-
>
|
|
195
|
+
> **Vì sao trạm này chạy CẢ PRD chứ không từng UC** *(B11)*. Ba lý do, theo thứ tự quan trọng:
|
|
196
|
+
>
|
|
197
|
+
> 1. **Mâu thuẫn chéo UC chỉ lộ ra khi đọc cùng lúc.** UC1 nói một kiểu, UC3 nói kiểu khác —
|
|
198
|
+
> chạy tách từng UC thì về **cấu trúc** là không thể thấy, không phải "khó thấy".
|
|
199
|
+
> 2. **Rẻ hơn.** PRD, bản thiết kế, tài liệu kỹ thuật là nguồn **dùng chung**; chạy per-UC là
|
|
200
|
+
> đọc lại chúng mỗi UC một lượt. Phần dùng chung chiếm đa số đầu vào.
|
|
201
|
+
> 3. **Một tài liệu cho một tính năng** là cách PO và QC vốn làm việc — file gốc của đội QC
|
|
202
|
+
> (`DOC_GAP_FEAT-02-3.md`) không có hậu tố UC, và `qa-planner/test-plan.md` vốn viết
|
|
203
|
+
> *"Test Plan cho một feature"*.
|
|
227
204
|
|
|
228
205
|
---
|
|
229
206
|
|
|
230
207
|
## Đối chiếu tài liệu kỹ thuật *(nguồn thứ hai — bắt lệch nghiệp vụ ↔ kỹ thuật)*
|
|
231
208
|
|
|
232
209
|
Định vị tech-doc gộp cấp PRD: `{paths.tech_docs_dir}/{domain}/{prd-slug}/tech-docs/{TICKET-ID}-tech-design.md`.
|
|
233
|
-
Nó phủ **nhiều UC** —
|
|
210
|
+
Nó phủ **nhiều UC** — và trạm này cũng phủ nhiều UC, nên đọc **mọi phần chạm `uc_list`**
|
|
211
|
+
(đối chiếu `@trace.ucs` ở header với `uc_list`). Phần thuộc UC ngoài phạm vi (`⏸ Chưa xét`) thì bỏ qua.
|
|
212
|
+
|
|
213
|
+
> **Đây là chỗ layout cấp PRD trả lãi rõ nhất.** Tech-doc gộp là **một** tài liệu phủ cả PRD.
|
|
214
|
+
> Chạy per-UC thì nó bị đọc lại N lần, mỗi lần lọc bỏ gần hết — và mâu thuẫn giữa hai UC trong
|
|
215
|
+
> **cùng** tài liệu đó không lần nào lộ ra, vì không lần nào thấy cả hai.
|
|
234
216
|
|
|
235
217
|
**Không tìm thấy → cảnh báo mềm, KHÔNG chặn** (dự án có thể chưa dựng tech-doc):
|
|
236
218
|
```
|
|
@@ -259,9 +241,9 @@ Nó phủ **nhiều UC** — lọc theo `@trace.ucs` ở header, chỉ đọc ph
|
|
|
259
241
|
Tech-doc có sổ ẩn số thiết kế riêng (`§12`), với vòng đời và người chịu trách nhiệm riêng, và
|
|
260
242
|
`/generate-code` đã canh nó. **Trạm này chỉ đọc, tuyệt đối không ghi vào.**
|
|
261
243
|
|
|
262
|
-
Với mỗi mục `open` trong §12 chạm `
|
|
244
|
+
Với mỗi mục `open` trong §12 chạm **bất kỳ UC trong `uc_list`**:
|
|
263
245
|
- **KHÔNG mở gap mới** trong `DOC_GAP.md` về cùng chuyện đó.
|
|
264
|
-
- Ghi vào `REQUIREMENT_ANALYSIS.md` mục *"Đang chờ chốt (từ §12 tech-doc)"*: `{id}` · điều chưa biết · owner · severity.
|
|
246
|
+
- Ghi vào `REQUIREMENT_ANALYSIS.md` mục *"Đang chờ chốt (từ §12 tech-doc)"*: `{id}` · **UC** · điều chưa biết · owner · severity.
|
|
265
247
|
- Test case chạm nó về sau sẽ bị chặn — nhưng bị chặn bởi **một mục đã có người xử lý**, không phải bởi một câu hỏi mới gửi PO.
|
|
266
248
|
|
|
267
249
|
> **Vì sao không ghi vào.** Một ẩn số đã nằm trong §12 nghĩa là **đã có người đang lo**: có
|
|
@@ -272,8 +254,8 @@ Với mỗi mục `open` trong §12 chạm `{UC-ID}`:
|
|
|
272
254
|
|
|
273
255
|
**Ngoại lệ — mục `spec-defect` là việc của PO.** §12 phân ba loại: `nội tại` (backend tự quyết) ·
|
|
274
256
|
`cross-service` (đội khác) · `spec-defect` (PRD/BDD sai hoặc thiếu). Hai loại đầu → ghi "đang chờ".
|
|
275
|
-
Loại thứ ba **đúng là gap tài liệu** → vẫn ghi vào `DOC_GAP.md
|
|
276
|
-
không đếm hai lần.
|
|
257
|
+
Loại thứ ba **đúng là gap tài liệu** → vẫn ghi vào `DOC_GAP.md` (cột `UC` = UC bị chạm), trỏ
|
|
258
|
+
ngược về `{id}` của §12 để không đếm hai lần.
|
|
277
259
|
|
|
278
260
|
---
|
|
279
261
|
|
|
@@ -301,7 +283,8 @@ Thứ tự điển hình: spec-breakdown → business-rules / data-flow → acce
|
|
|
301
283
|
|
|
302
284
|
File `.feature` chính thức đã định nghĩa scenario là `@trace.scenario={UC-ID}-SC{N}` với
|
|
303
285
|
`@trace.business_rules`. Map mọi `BR-xx` / `AC-xx` bạn tạo ra tới `{UC-ID}-SC{N}` sở hữu nó
|
|
304
|
-
và ghi lại mapping —
|
|
286
|
+
và ghi lại mapping — **làm cho từng UC trong `uc_list`**, và `BR`/`AC` phải mang rõ UC của nó
|
|
287
|
+
(một file phân tích giờ phủ nhiều UC, nên `BR-01` không còn tự phân biệt được là của UC nào) — qc-design-test và qc-run-test cần nó để gắn tag
|
|
305
288
|
`@trace.verifies` cho test và ghi `qc_status` theo từng scenario.
|
|
306
289
|
|
|
307
290
|
## Quét gap — hai nguồn, gộp rồi mới thẩm định
|
|
@@ -367,13 +350,23 @@ Gộp gap từ **cả hai nguồn** vào một tập trước khi sang bước t
|
|
|
367
350
|
|
|
368
351
|
## DOC_GAP (bắt buộc)
|
|
369
352
|
|
|
370
|
-
Luôn tạo
|
|
371
|
-
|
|
353
|
+
Luôn tạo **đúng MỘT** file gap cho cả (PRD × nền) theo
|
|
354
|
+
`{paths.qc_skills_dir}/qa-analyst/DOC_GAP.template.md` — các UC là các hàng bên trong, phân
|
|
355
|
+
biệt bằng cột `UC`:
|
|
356
|
+
- **Bảng 11 cột**, cột 2 là `UC`. ID gap `GAP-UC{N}-{nnn}` (vd `GAP-UC1-001`); gap thuộc cả
|
|
357
|
+
PRD → `GAP-GEN-{nnn}`. Đánh số **độc lập trong từng UC** — phân tích lại UC1 KHÔNG được làm
|
|
358
|
+
đổi số gap của UC2, vì test case đã có đang trỏ `🚫 Block: [GAP-UC2-003]`.
|
|
359
|
+
- **Section `Phạm vi phân tích`** — mỗi UC một hàng kèm `@trace.status`, đã phân tích chưa, số
|
|
360
|
+
gap. UC ngoài phạm vi ghi `⏸ Chưa xét`, **không bỏ khỏi bảng**.
|
|
361
|
+
- Mỗi gap phân loại MISSING / AMBIGUOUS / CONTRADICTORY / ASSUMPTION / OPEN QUESTION, với severity (🔴 Blocker → ⚪ Low) và function/BR/AC bị ảnh hưởng.
|
|
372
362
|
- Không bao giờ bịa câu trả lời; đánh dấu giả định là `ASSUMPTION` để PO/dev confirm.
|
|
373
|
-
- Bất kỳ `🔴 Blocker` nào còn `Open` ⇒ UC
|
|
363
|
+
- Bất kỳ `🔴 Blocker` nào còn `Open` ⇒ **UC ở cột `UC` của hàng đó** chưa sẵn sàng cho
|
|
364
|
+
qc-design-test — bàn giao cho qc-plan. *Chặn theo từng UC, KHÔNG chặn cả PRD:* một blocker ở
|
|
365
|
+
UC3 không có lý do gì dừng việc thiết kế test cho UC1. Ghi rõ UC nào bị chặn ở report.
|
|
374
366
|
- **Đẩy các defect spec thực sự lên PO (không chỉ giữ local).** Một blocker là lỗi thật
|
|
375
367
|
trong spec chính thức — `AMBIGUOUS` / `CONTRADICTORY` / `MISSING` trong PRD/BDD — phải tới
|
|
376
368
|
PO qua feedback flow, không chỉ nằm trong `DOC_GAP.md`: tạo `/report-bug {UC-ID} {desc}`
|
|
369
|
+
(`{UC-ID}` lấy từ cột `UC` của hàng gap — bug đi theo UC, không theo PRD)
|
|
377
370
|
(BUG_FLOW của nó phân loại PRD vs BDD), hoặc `/propose-scenario {UC-ID}` nếu gap là thiếu test
|
|
378
371
|
coverage. Gap `ASSUMPTION` / `OPEN QUESTION` được confirm qua questions-for-dev của qc-plan — không file thành bug.
|
|
379
372
|
|
|
@@ -399,18 +392,28 @@ nó bị loại. Cập nhật `Tổng số gap` + bảng ưu tiên sau khi áp v
|
|
|
399
392
|
|
|
400
393
|
## Output
|
|
401
394
|
|
|
402
|
-
Ghi **hai file** dưới `{paths.qc_dir}/{
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
395
|
+
Ghi **hai file** dưới `{qc_artifact_dir}` (= `{paths.qc_dir}/{TICKET-ID}/{active_platform}/`)
|
|
396
|
+
+ **một** dưới `{paths.refinement_dir}/`.
|
|
397
|
+
|
|
398
|
+
**Mỗi loại đúng MỘT file cho cả PRD** — đừng tách một-file-mỗi-UC, và cũng đừng tách
|
|
399
|
+
một-file-mỗi-bước (không có file spec-breakdown / business-rules / data-flow / AC riêng):
|
|
400
|
+
|
|
401
|
+
1. **`{qc_artifact_dir}REQUIREMENT_ANALYSIS.md`** — bản phân tích hợp nhất duy nhất cho cả PRD.
|
|
402
|
+
Mở đầu bằng **bảng `Phạm vi phân tích`** (cùng nội dung với bảng trong `DOC_GAP.md`), rồi
|
|
403
|
+
**một mục cho mỗi UC trong phạm vi**, mỗi mục theo thứ tự: phân rã requirement → bảng
|
|
404
|
+
business-rule (`BR-xx`) → data-flow → acceptance-criteria (`AC-xx`), mỗi `BR`/`AC` map tới
|
|
405
|
+
`{UC-ID}-SC{N}` (của `.feature` nền này) sở hữu nó.
|
|
406
|
+
Thêm một mục **"Mâu thuẫn chéo UC"** — chỗ hai UC của cùng PRD nói khác nhau. Rỗng thì ghi
|
|
407
|
+
"Không có". *Đây là thứ chỉ trạm cấp PRD nhìn thấy được; đừng bỏ mục.*
|
|
408
|
+
Cuối file thêm mục **"Đang chờ chốt (từ §12 tech-doc)"** — các ẩn số thiết kế `open` chạm
|
|
409
|
+
các UC trong phạm vi (`{id}` · UC · điều chưa biết · owner · severity). Rỗng thì ghi
|
|
410
|
+
"Không có"; **đừng bỏ mục**.
|
|
411
|
+
2. **`{qc_artifact_dir}DOC_GAP.md`** — file gap, theo
|
|
411
412
|
`{paths.qc_skills_dir}/qa-analyst/DOC_GAP.template.md` + luật viết ở
|
|
412
413
|
`{paths.qc_skills_dir}/qa-analyst/spec-issue-reporter.md`. Bắt buộc:
|
|
413
|
-
- **Bảng
|
|
414
|
+
- **Bảng 11 cột** đúng thứ tự, có cột **`UC`** (cột 2) và cột **Giao cho đội** (Dev / PO / BA / Design / Kiến trúc / Dữ liệu).
|
|
415
|
+
- Section **"Phạm vi phân tích"** ngay sau metadata — mỗi UC một hàng kèm `@trace.status`,
|
|
416
|
+
đã phân tích chưa, số gap. UC ngoài phạm vi ghi `⏸ Chưa xét`.
|
|
414
417
|
- Ô câu hỏi đủ **bốn phần** tách bằng `<br/>`: **Bối cảnh → Vấn đề → Tại sao quan trọng → Gợi ý**.
|
|
415
418
|
*Ba phần đầu cho PO xếp ưu tiên; phần cuối cho PO trả lời nhanh mà không phải nghĩ lại từ đầu.*
|
|
416
419
|
- Section **"Tài liệu đầu vào đã đọc để phân tích"** đặt ngay sau metadata — liệt kê **đủ** mọi
|
|
@@ -418,7 +421,7 @@ thành một-file-mỗi-bước (không có file spec-breakdown / business-rules
|
|
|
418
421
|
với *"chưa đọc"*.
|
|
419
422
|
- Mức nặng nhất dùng từ **`🔴 Blocker`** (không phải `Critical`) — `/qc-run-test` đọc đúng từ này
|
|
420
423
|
để đặt *"scenario đang chờ PO"* vào sổ trace.
|
|
421
|
-
3. **`{paths.refinement_dir}/{
|
|
424
|
+
3. **`{paths.refinement_dir}/{TICKET-ID}-qa-findings.yaml`** — **cùng dữ liệu gap**, ở định dạng Review Board đọc được. Xem §Bản findings dưới đây.
|
|
422
425
|
|
|
423
426
|
`{paths.qc_dir}` là folder top-level NHÌN THẤY trong QC repo (mặc định `docs/`, **không** phải
|
|
424
427
|
`.agent/review/` ẩn) để team QC mở và xử lý output dễ dàng. Spec chính thức ở lại
|
|
@@ -433,8 +436,10 @@ Dùng **đúng schema của `/refine-prd`** để Review Board đọc được c
|
|
|
433
436
|
|
|
434
437
|
```yaml
|
|
435
438
|
prd_source: "{paths.specs_dir}/{domain}/{prd-slug}/{TICKET-ID}-{prd-slug}.md"
|
|
436
|
-
|
|
439
|
+
ticket_id: "{TICKET-ID}"
|
|
437
440
|
platform: "{active_platform}"
|
|
441
|
+
ucs: ["{UC-ID}", "…"] # các UC TRONG phạm vi (approved) — theo thứ tự
|
|
442
|
+
ucs_skipped: ["{UC-ID}"] # UC chưa xét, kèm lý do ở DOC_GAP §Phạm vi phân tích
|
|
438
443
|
generated_at: "{ISO datetime}"
|
|
439
444
|
generated_by: "qc-analyze"
|
|
440
445
|
status: "pending_review"
|
|
@@ -452,7 +457,7 @@ findings:
|
|
|
452
457
|
auto_fixable: false # LUÔN false — xem cảnh báo dưới
|
|
453
458
|
status: "pending"
|
|
454
459
|
applied_via: ""
|
|
455
|
-
gap_ref: "GAP-
|
|
460
|
+
gap_ref: "GAP-UC1-001" # trỏ ngược về hàng trong DOC_GAP.md (ID mang UC)
|
|
456
461
|
|
|
457
462
|
summary:
|
|
458
463
|
total_findings: {N}
|
|
@@ -473,8 +478,9 @@ summary:
|
|
|
473
478
|
> Đường đúng vẫn là kênh đã có: `/report-bug` cho defect spec thật, `/propose-scenario` cho thiếu
|
|
474
479
|
> độ phủ. File `.yaml` này để **PO đọc và quyết trong một chỗ quen**, không phải để máy tự áp.
|
|
475
480
|
|
|
476
|
-
**File riêng, không ghi chung với `/refine-prd`.**
|
|
477
|
-
`{
|
|
481
|
+
**File riêng, không ghi chung với `/refine-prd`.** Cả hai giờ đều ở cấp PRD, nên khác biệt nằm
|
|
482
|
+
ở **hậu tố**: `{TICKET-ID}-qa-findings.yaml` (trạm này) vs `{prd-slug}-findings.yaml`
|
|
483
|
+
(`/refine-prd`). Đừng gộp. Ghi chung sẽ phá trường `applied_to_version` mà `/refine-prd` dùng để
|
|
478
484
|
phân biệt *"PRD đổi do chính tôi áp fix"* với *"có người lạ sửa"* — và nó sẽ mãi mãi tưởng có
|
|
479
485
|
người sửa sau lưng, mỗi lần chạy đều quét lại toàn bộ kèm cảnh báo giả.
|
|
480
486
|
|
|
@@ -486,17 +492,21 @@ người sửa sau lưng, mỗi lần chạy đều quét lại toàn bộ kèm
|
|
|
486
492
|
Output Artifacts · Next) cho report cuối, kèm khối bên dưới.
|
|
487
493
|
|
|
488
494
|
```
|
|
489
|
-
/qc-analyze Hoàn tất — {
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
495
|
+
/qc-analyze Hoàn tất — {TICKET-ID} ({active_platform})
|
|
496
|
+
Phạm vi: {n}/{N} UC phân tích{nếu có UC chưa xét: " · ⏸ {m} chưa xét: {danh sách UC-ID} (BDD chưa approved)"}
|
|
497
|
+
Files : {paths.qc_dir}/{TICKET-ID}/{active_platform}/REQUIREMENT_ANALYSIS.md + DOC_GAP.md (11 cột)
|
|
498
|
+
{paths.refinement_dir}/{TICKET-ID}-qa-findings.yaml ← mở bằng Review Board (chuột phải)
|
|
499
|
+
Nguồn : PRD · BDD({active_platform}, {n} UC) · design-spec · tech-doc{nếu thiếu tech-doc: " (THIẾU — không đối chiếu được nghiệp vụ ↔ kỹ thuật)"}
|
|
493
500
|
Quét : 4 kỹ năng phân tích + 4 lăng kính (xử lý lỗi · giao diện · dữ liệu & cấu hình
|
|
494
501
|
· đối chiếu chéo: PRD↔design-spec, bdd↔design-spec)
|
|
495
502
|
Verify: {raw} gap thô → {N} còn Open (❌ {invalid} bịa/đã-trả-lời · ⚠️ {reclass} không phải gap nghiệp vụ · 🔁 {merge} trùng)
|
|
496
|
-
Gaps : {N} ({blockers} blocker)
|
|
497
|
-
|
|
503
|
+
Gaps : {N} ({blockers} blocker) — theo UC: {UC1: n · UC2: n · …}{nếu có: " · toàn PRD: {n}"}
|
|
504
|
+
← blocker là spec-defect? → /report-bug {UC-ID của hàng đó} | coverage gap → /propose-scenario {UC-ID}
|
|
505
|
+
Chéo UC: {X} mâu thuẫn giữa các UC của cùng PRD (đã ghi vào REQUIREMENT_ANALYSIS §Mâu thuẫn chéo UC)
|
|
506
|
+
Chặn : {danh sách UC có 🔴 Blocker còn Open} — các UC còn lại vẫn thiết kế test được bình thường
|
|
507
|
+
Chờ chốt: {G} ẩn số §12 tech-doc đang open chạm các UC này (đã ghi vào REQUIREMENT_ANALYSIS, KHÔNG hỏi lại PO)
|
|
498
508
|
SC map: {M} BR/AC map tới {K} scenario
|
|
499
|
-
Next : /qc-plan {
|
|
509
|
+
Next : /qc-plan {TICKET-ID} {active_platform} ← rủi ro / what-if / câu hỏi cho dev
|
|
500
510
|
(giải quyết các gap 🔴 Blocker với PO/Dev trước)
|
|
501
511
|
```
|
|
502
512
|
|