sdtk-kit 0.3.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/README.md +131 -0
- package/assets/manifest/toolkit-bundle.manifest.json +303 -0
- package/assets/manifest/toolkit-bundle.sha256.txt +59 -0
- package/assets/toolkit/toolkit/AGENTS.md +103 -0
- package/assets/toolkit/toolkit/install.ps1 +155 -0
- package/assets/toolkit/toolkit/runtimes/claude/CLAUDE_TEMPLATE.md +32 -0
- package/assets/toolkit/toolkit/runtimes/codex/CODEX_TEMPLATE.md +32 -0
- package/assets/toolkit/toolkit/scripts/init-feature.ps1 +253 -0
- package/assets/toolkit/toolkit/scripts/install-codex-skills.ps1 +181 -0
- package/assets/toolkit/toolkit/scripts/uninstall-codex-skills.ps1 +116 -0
- package/assets/toolkit/toolkit/sdtk.config.json +28 -0
- package/assets/toolkit/toolkit/sdtk.config.profiles.example.json +50 -0
- package/assets/toolkit/toolkit/skills/sdtk-api-design-spec/SKILL.md +78 -0
- package/assets/toolkit/toolkit/skills/sdtk-api-design-spec/references/API_DESIGN_CREATION_RULES.md +212 -0
- package/assets/toolkit/toolkit/skills/sdtk-api-design-spec/references/FLOWCHART_CREATION_RULES.md +397 -0
- package/assets/toolkit/toolkit/skills/sdtk-api-design-spec/scripts/generate_api_design_detail.py +565 -0
- package/assets/toolkit/toolkit/skills/sdtk-api-doc/SKILL.md +36 -0
- package/assets/toolkit/toolkit/skills/sdtk-api-doc/references/FLOWCHART_CREATION_RULES.md +397 -0
- package/assets/toolkit/toolkit/skills/sdtk-arch/SKILL.md +43 -0
- package/assets/toolkit/toolkit/skills/sdtk-arch/references/API_DESIGN_CREATION_RULES.md +212 -0
- package/assets/toolkit/toolkit/skills/sdtk-arch/references/FLOWCHART_CREATION_RULES.md +397 -0
- package/assets/toolkit/toolkit/skills/sdtk-arch/references/FLOW_ACTION_SPEC_CREATION_RULES.md +136 -0
- package/assets/toolkit/toolkit/skills/sdtk-ba/SKILL.md +24 -0
- package/assets/toolkit/toolkit/skills/sdtk-design-layout/SKILL.md +21 -0
- package/assets/toolkit/toolkit/skills/sdtk-dev/SKILL.md +20 -0
- package/assets/toolkit/toolkit/skills/sdtk-dev-backend/SKILL.md +17 -0
- package/assets/toolkit/toolkit/skills/sdtk-dev-frontend/SKILL.md +15 -0
- package/assets/toolkit/toolkit/skills/sdtk-orchestrator/SKILL.md +44 -0
- package/assets/toolkit/toolkit/skills/sdtk-pm/SKILL.md +26 -0
- package/assets/toolkit/toolkit/skills/sdtk-qa/SKILL.md +22 -0
- package/assets/toolkit/toolkit/skills/sdtk-screen-design-spec/SKILL.md +59 -0
- package/assets/toolkit/toolkit/skills/sdtk-screen-design-spec/references/FLOW_ACTION_SPEC_CREATION_RULES.md +136 -0
- package/assets/toolkit/toolkit/skills/sdtk-screen-design-spec/references/excel-image-export.md +51 -0
- package/assets/toolkit/toolkit/skills/sdtk-screen-design-spec/references/figma-mcp.md +54 -0
- package/assets/toolkit/toolkit/skills/sdtk-screen-design-spec/references/numbering-rules.md +76 -0
- package/assets/toolkit/toolkit/skills/sdtk-screen-design-spec/scripts/renumber_flow_action_spec_global.py +136 -0
- package/assets/toolkit/toolkit/skills/sdtk-screen-design-spec/scripts/validate_flow_action_spec_numbering.py +249 -0
- package/assets/toolkit/toolkit/skills/sdtk-test-case-spec/SKILL.md +65 -0
- package/assets/toolkit/toolkit/skills/sdtk-test-case-spec/references/TEST_CASE_CREATION_RULES.md +129 -0
- package/assets/toolkit/toolkit/skills/sdtk-test-case-spec/scripts/validate_test_case_spec.py +97 -0
- package/assets/toolkit/toolkit/templates/QUALITY_CHECKLIST.md +124 -0
- package/assets/toolkit/toolkit/templates/README.md +56 -0
- package/assets/toolkit/toolkit/templates/SHARED_PLANNING.md +80 -0
- package/assets/toolkit/toolkit/templates/docs/api/API_DESIGN_CREATION_RULES.md +212 -0
- package/assets/toolkit/toolkit/templates/docs/api/API_DESIGN_DETAIL_TEMPLATE.md +62 -0
- package/assets/toolkit/toolkit/templates/docs/api/API_ENDPOINTS_TEMPLATE.md +229 -0
- package/assets/toolkit/toolkit/templates/docs/api/FEATURE_API_TEMPLATE.yaml +20 -0
- package/assets/toolkit/toolkit/templates/docs/api/FLOWCHART_CREATION_RULES.md +397 -0
- package/assets/toolkit/toolkit/templates/docs/api/feature_api_flow_list_TEMPLATE.txt +12 -0
- package/assets/toolkit/toolkit/templates/docs/architecture/ARCH_DESIGN_TEMPLATE.md +109 -0
- package/assets/toolkit/toolkit/templates/docs/database/DATABASE_SPEC_TEMPLATE.md +175 -0
- package/assets/toolkit/toolkit/templates/docs/design/DESIGN_LAYOUT_TEMPLATE.md +49 -0
- package/assets/toolkit/toolkit/templates/docs/dev/FEATURE_IMPL_PLAN_TEMPLATE.md +73 -0
- package/assets/toolkit/toolkit/templates/docs/product/BACKLOG_TEMPLATE.md +50 -0
- package/assets/toolkit/toolkit/templates/docs/product/PRD_TEMPLATE.md +66 -0
- package/assets/toolkit/toolkit/templates/docs/product/PROJECT_INITIATION_TEMPLATE.md +98 -0
- package/assets/toolkit/toolkit/templates/docs/qa/QA_RELEASE_REPORT_TEMPLATE.md +61 -0
- package/assets/toolkit/toolkit/templates/docs/qa/TEST_CASE_CREATION_RULES.md +129 -0
- package/assets/toolkit/toolkit/templates/docs/qa/TEST_CASE_TEMPLATE.md +104 -0
- package/assets/toolkit/toolkit/templates/docs/specs/BA_SPEC_TEMPLATE.md +139 -0
- package/assets/toolkit/toolkit/templates/docs/specs/FLOW_ACTION_SPEC_CREATION_RULES.md +136 -0
- package/assets/toolkit/toolkit/templates/docs/specs/FLOW_ACTION_SPEC_TEMPLATE.md +160 -0
- package/bin/sdtk.js +15 -0
- package/package.json +47 -0
- package/src/commands/auth.js +85 -0
- package/src/commands/generate.js +177 -0
- package/src/commands/help.js +69 -0
- package/src/commands/init.js +73 -0
- package/src/index.js +56 -0
- package/src/lib/args.js +116 -0
- package/src/lib/errors.js +41 -0
- package/src/lib/github-access.js +68 -0
- package/src/lib/powershell.js +85 -0
- package/src/lib/state.js +83 -0
- package/src/lib/toolkit-payload.js +99 -0
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import re
|
|
5
|
+
import sys
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
TABLE_ROW_RE = re.compile(r"^\|.*\|\s*$")
|
|
11
|
+
TABLE_SEP_RE = re.compile(r"^\|\s*:?-+:?\s*(\|\s*:?-+:?\s*)+\|\s*$")
|
|
12
|
+
HEADING_RE = re.compile(r"^(#{1,6})\s+(.*\S)\s*$")
|
|
13
|
+
VI_DIACRITIC_RE = re.compile(r"[À-ỹ]")
|
|
14
|
+
VI_PHRASE_RE = re.compile(
|
|
15
|
+
r"\b("
|
|
16
|
+
r"thuc thi|hien thi|cap nhat|bo sung|can xac nhan|trong anh|"
|
|
17
|
+
r"duoc tra kem|tao lich|theo user|muc global|thay the cho|bao gom"
|
|
18
|
+
r")\b",
|
|
19
|
+
re.IGNORECASE,
|
|
20
|
+
)
|
|
21
|
+
INLINE_HEADING_RE = re.compile(r".+\s#{2,}\s+\S")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass(frozen=True)
|
|
25
|
+
class Occurrence:
|
|
26
|
+
number: int
|
|
27
|
+
section: str
|
|
28
|
+
line_no: int
|
|
29
|
+
raw_line: str
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _split_table_row(line: str) -> list[str]:
|
|
33
|
+
# Keep it simple: markdown tables in our spec are plain and don't escape pipes.
|
|
34
|
+
parts = [p.strip() for p in line.strip().strip("|").split("|")]
|
|
35
|
+
return parts
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _read_text(path: Path) -> str:
|
|
39
|
+
# Prefer UTF-8; fallback to cp1252-ish if user saved without UTF-8.
|
|
40
|
+
for enc in ("utf-8", "utf-8-sig", "cp1252"):
|
|
41
|
+
try:
|
|
42
|
+
return path.read_text(encoding=enc)
|
|
43
|
+
except UnicodeDecodeError:
|
|
44
|
+
continue
|
|
45
|
+
return path.read_text(errors="replace")
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def collect_hygiene_issues(md_text: str, *, en_check: bool) -> dict[str, list[tuple[int, str]]]:
|
|
49
|
+
issues: dict[str, list[tuple[int, str]]] = {
|
|
50
|
+
"encoding": [],
|
|
51
|
+
"vi_diacritic": [],
|
|
52
|
+
"vi_phrase": [],
|
|
53
|
+
"inline_heading": [],
|
|
54
|
+
}
|
|
55
|
+
lines = md_text.splitlines()
|
|
56
|
+
in_code_block = False
|
|
57
|
+
|
|
58
|
+
for idx, line in enumerate(lines, start=1):
|
|
59
|
+
stripped = line.strip()
|
|
60
|
+
if stripped.startswith("```"):
|
|
61
|
+
in_code_block = not in_code_block
|
|
62
|
+
continue
|
|
63
|
+
if in_code_block:
|
|
64
|
+
continue
|
|
65
|
+
|
|
66
|
+
if "�" in line or "ↁE" in line:
|
|
67
|
+
issues["encoding"].append((idx, line))
|
|
68
|
+
|
|
69
|
+
# A common corruption symptom: merged headings inside normal text lines.
|
|
70
|
+
if INLINE_HEADING_RE.search(line) and not stripped.startswith("#"):
|
|
71
|
+
issues["inline_heading"].append((idx, line))
|
|
72
|
+
|
|
73
|
+
if en_check:
|
|
74
|
+
lowered = stripped.lower()
|
|
75
|
+
if "original text" in lowered:
|
|
76
|
+
continue
|
|
77
|
+
if VI_DIACRITIC_RE.search(line):
|
|
78
|
+
issues["vi_diacritic"].append((idx, line))
|
|
79
|
+
elif VI_PHRASE_RE.search(line):
|
|
80
|
+
issues["vi_phrase"].append((idx, line))
|
|
81
|
+
|
|
82
|
+
return issues
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def parse_action_tables(md_text: str) -> list[Occurrence]:
|
|
86
|
+
occurrences: list[Occurrence] = []
|
|
87
|
+
current_section = ""
|
|
88
|
+
lines = md_text.splitlines()
|
|
89
|
+
|
|
90
|
+
i = 0
|
|
91
|
+
while i < len(lines):
|
|
92
|
+
line = lines[i]
|
|
93
|
+
|
|
94
|
+
m = HEADING_RE.match(line)
|
|
95
|
+
if m:
|
|
96
|
+
current_section = m.group(2).strip()
|
|
97
|
+
|
|
98
|
+
# Detect table header
|
|
99
|
+
if i + 1 < len(lines) and TABLE_ROW_RE.match(line) and TABLE_ROW_RE.match(lines[i + 1]):
|
|
100
|
+
header = _split_table_row(line)
|
|
101
|
+
sep = lines[i + 1]
|
|
102
|
+
|
|
103
|
+
if not TABLE_SEP_RE.match(sep):
|
|
104
|
+
i += 1
|
|
105
|
+
continue
|
|
106
|
+
|
|
107
|
+
# Only validate action tables: must contain No + Action + Description
|
|
108
|
+
lowered = [h.lower() for h in header]
|
|
109
|
+
if "no" not in lowered and "no." not in lowered:
|
|
110
|
+
i += 1
|
|
111
|
+
continue
|
|
112
|
+
if "action" not in lowered or "description" not in lowered:
|
|
113
|
+
i += 1
|
|
114
|
+
continue
|
|
115
|
+
|
|
116
|
+
try:
|
|
117
|
+
no_index = lowered.index("no")
|
|
118
|
+
except ValueError:
|
|
119
|
+
no_index = lowered.index("no.")
|
|
120
|
+
|
|
121
|
+
# Consume rows until table ends
|
|
122
|
+
j = i + 2
|
|
123
|
+
while j < len(lines) and TABLE_ROW_RE.match(lines[j]):
|
|
124
|
+
row = _split_table_row(lines[j])
|
|
125
|
+
if len(row) <= no_index:
|
|
126
|
+
j += 1
|
|
127
|
+
continue
|
|
128
|
+
raw_no = row[no_index]
|
|
129
|
+
try:
|
|
130
|
+
number = int(raw_no)
|
|
131
|
+
except ValueError:
|
|
132
|
+
j += 1
|
|
133
|
+
continue
|
|
134
|
+
occurrences.append(
|
|
135
|
+
Occurrence(
|
|
136
|
+
number=number,
|
|
137
|
+
section=current_section or "(unknown section)",
|
|
138
|
+
line_no=j + 1, # 1-based
|
|
139
|
+
raw_line=lines[j],
|
|
140
|
+
)
|
|
141
|
+
)
|
|
142
|
+
j += 1
|
|
143
|
+
|
|
144
|
+
i = j
|
|
145
|
+
continue
|
|
146
|
+
|
|
147
|
+
i += 1
|
|
148
|
+
|
|
149
|
+
return occurrences
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def main() -> int:
|
|
153
|
+
parser = argparse.ArgumentParser(description="Validate numbering in flow-action spec tables.")
|
|
154
|
+
parser.add_argument("--spec", required=True, help="Path to *_FLOW_ACTION_SPEC.md")
|
|
155
|
+
parser.add_argument(
|
|
156
|
+
"--en-check",
|
|
157
|
+
action="store_true",
|
|
158
|
+
help="Enable EN artifact hygiene checks (Vietnamese leftovers + encoding corruption).",
|
|
159
|
+
)
|
|
160
|
+
args = parser.parse_args()
|
|
161
|
+
|
|
162
|
+
try:
|
|
163
|
+
sys.stdout.reconfigure(encoding="utf-8") # type: ignore[attr-defined]
|
|
164
|
+
sys.stderr.reconfigure(encoding="utf-8") # type: ignore[attr-defined]
|
|
165
|
+
except Exception:
|
|
166
|
+
pass
|
|
167
|
+
|
|
168
|
+
spec_path = Path(args.spec)
|
|
169
|
+
if not spec_path.exists():
|
|
170
|
+
print(f"[ERROR] Not found: {spec_path}", file=sys.stderr)
|
|
171
|
+
return 2
|
|
172
|
+
|
|
173
|
+
text = _read_text(spec_path)
|
|
174
|
+
occ = parse_action_tables(text)
|
|
175
|
+
if not occ:
|
|
176
|
+
print("[WARN] No action tables detected (| No | Action | Description | ... |).")
|
|
177
|
+
return 0
|
|
178
|
+
|
|
179
|
+
by_number: dict[int, list[Occurrence]] = {}
|
|
180
|
+
for o in occ:
|
|
181
|
+
by_number.setdefault(o.number, []).append(o)
|
|
182
|
+
|
|
183
|
+
duplicates = {n: os for n, os in by_number.items() if len(os) > 1}
|
|
184
|
+
|
|
185
|
+
max_seen = -1
|
|
186
|
+
decreases: list[tuple[Occurrence, int]] = []
|
|
187
|
+
for o in occ:
|
|
188
|
+
if o.number < max_seen:
|
|
189
|
+
decreases.append((o, max_seen))
|
|
190
|
+
max_seen = max(max_seen, o.number)
|
|
191
|
+
|
|
192
|
+
has_issues = bool(duplicates or decreases)
|
|
193
|
+
hygiene = collect_hygiene_issues(text, en_check=args.en_check)
|
|
194
|
+
if hygiene["encoding"] or hygiene["inline_heading"]:
|
|
195
|
+
has_issues = True
|
|
196
|
+
if args.en_check and (hygiene["vi_diacritic"] or hygiene["vi_phrase"]):
|
|
197
|
+
has_issues = True
|
|
198
|
+
|
|
199
|
+
print(f"Checked: {spec_path}")
|
|
200
|
+
print(f"- Total numbered rows: {len(occ)}")
|
|
201
|
+
print(f"- Unique numbers: {len(by_number)}")
|
|
202
|
+
print(f"- EN hygiene check enabled: {args.en_check}")
|
|
203
|
+
|
|
204
|
+
if duplicates:
|
|
205
|
+
print("\n[FAIL] Duplicate numbers found:")
|
|
206
|
+
for n in sorted(duplicates.keys()):
|
|
207
|
+
print(f"- No {n}:")
|
|
208
|
+
for o in duplicates[n]:
|
|
209
|
+
print(f" - {o.section} (line {o.line_no})")
|
|
210
|
+
|
|
211
|
+
if decreases:
|
|
212
|
+
print("\n[FAIL] Numbering decreases/resets detected (global numbering policy):")
|
|
213
|
+
for o, prev_max in decreases:
|
|
214
|
+
print(f"- No {o.number} after max {prev_max}: {o.section} (line {o.line_no})")
|
|
215
|
+
|
|
216
|
+
if hygiene["encoding"]:
|
|
217
|
+
print("\n[FAIL] Encoding/mojibake markers detected:")
|
|
218
|
+
for line_no, line in hygiene["encoding"][:20]:
|
|
219
|
+
print(f"- line {line_no}: {line.strip()}")
|
|
220
|
+
|
|
221
|
+
if hygiene["inline_heading"]:
|
|
222
|
+
print("\n[FAIL] Inline/merged heading patterns detected:")
|
|
223
|
+
for line_no, line in hygiene["inline_heading"][:20]:
|
|
224
|
+
print(f"- line {line_no}: {line.strip()}")
|
|
225
|
+
|
|
226
|
+
if args.en_check and hygiene["vi_diacritic"]:
|
|
227
|
+
print("\n[FAIL] Vietnamese diacritic text detected in EN artifact:")
|
|
228
|
+
for line_no, line in hygiene["vi_diacritic"][:20]:
|
|
229
|
+
print(f"- line {line_no}: {line.strip()}")
|
|
230
|
+
|
|
231
|
+
if args.en_check and hygiene["vi_phrase"]:
|
|
232
|
+
print("\n[FAIL] Vietnamese phrase patterns detected in EN artifact:")
|
|
233
|
+
for line_no, line in hygiene["vi_phrase"][:20]:
|
|
234
|
+
print(f"- line {line_no}: {line.strip()}")
|
|
235
|
+
|
|
236
|
+
if not has_issues:
|
|
237
|
+
print("\n[OK] Numbering and text hygiene checks passed.")
|
|
238
|
+
return 0
|
|
239
|
+
|
|
240
|
+
print("\nHint: Use global numbering across the full document.")
|
|
241
|
+
print("- Do not repeat No values in any action table.")
|
|
242
|
+
print("- Do not reset numbering per screen/dialog.")
|
|
243
|
+
print("- Keep EN artifacts free of Vietnamese leftovers and encoding corruption.")
|
|
244
|
+
print("- Keep headings/sections on separate lines (avoid merged markdown blocks).")
|
|
245
|
+
return 1
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
if __name__ == "__main__":
|
|
249
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sdtk-test-case-spec
|
|
3
|
+
description: Generate screen-based QA test-case markdown (`[FEATURE_KEY]_TEST_CASE.md`) in Excel-aligned layout (Statistic + per-screen UTC/ITC worksheets). Use when QA needs reusable test design artifacts before or during execution.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# SDTK Test Case Spec
|
|
7
|
+
|
|
8
|
+
## Outputs
|
|
9
|
+
- `docs/qa/[FEATURE_KEY]_TEST_CASE.md`
|
|
10
|
+
- Optional project variant:
|
|
11
|
+
- `docs/en/qa/[FEATURE_KEY]_TEST_CASE.md` (only when project uses `docs/en/**`)
|
|
12
|
+
|
|
13
|
+
## Required Inputs
|
|
14
|
+
- Feature key (`FEATURE_KEY`)
|
|
15
|
+
- Screen/flow references:
|
|
16
|
+
- `docs/specs/[FEATURE_KEY]_FLOW_ACTION_SPEC.md`
|
|
17
|
+
- `docs/specs/BA_SPEC_[FEATURE_KEY].md`
|
|
18
|
+
- API reference:
|
|
19
|
+
- `docs/api/[FEATURE_KEY]_ENDPOINTS.md`
|
|
20
|
+
- (optional) `docs/api/[FeaturePascal]_API.yaml`
|
|
21
|
+
- Clarification source:
|
|
22
|
+
- `docs/specs/Q&A.md` or `docs/en/specs/Q&A.md` when available
|
|
23
|
+
|
|
24
|
+
## Core Rules
|
|
25
|
+
1. Apply `./references/TEST_CASE_CREATION_RULES.md` first.
|
|
26
|
+
2. Keep section order fixed (Statistic -> Abbreviations -> Scope -> References -> Environment -> Coverage -> Screen-based UTC/ITC -> OQ -> STC/UAT note).
|
|
27
|
+
3. Use screen-first layout to mirror worksheet structure:
|
|
28
|
+
- each screen can have `[SCREEN_KEY]_UTC` and `[SCREEN_KEY]_ITC`.
|
|
29
|
+
4. Keep one unified 18-column schema for UTC/ITC rows.
|
|
30
|
+
5. Keep stable case IDs; do not renumber only because of regrouping.
|
|
31
|
+
6. Track unresolved decisions via `OQ-xx`.
|
|
32
|
+
|
|
33
|
+
## Procedure
|
|
34
|
+
1. Resolve output path:
|
|
35
|
+
- default `docs/qa/[FEATURE_KEY]_TEST_CASE.md`
|
|
36
|
+
- use `docs/en/qa/...` only if the repo already follows `docs/en/**`.
|
|
37
|
+
2. Build/refresh `Statistic Summary (Excel-aligned)`:
|
|
38
|
+
- include UT total, IT total, grand total.
|
|
39
|
+
3. Build `Feature Coverage Matrix` from flow/action and API docs.
|
|
40
|
+
4. Split UTC/ITC by screen sections (`screen-first`), not by test type only.
|
|
41
|
+
5. Fill conflict/permission/error-path cases from Q&A decisions and API contracts.
|
|
42
|
+
6. Record unresolved items in section `Open Questions`.
|
|
43
|
+
7. Validate:
|
|
44
|
+
- counts in summary match table rows
|
|
45
|
+
- no placeholder tokens like `??`
|
|
46
|
+
- out-of-scope boundaries are explicit
|
|
47
|
+
|
|
48
|
+
## Role Integration
|
|
49
|
+
- Primary owner: `/qa`.
|
|
50
|
+
- `/qa` uses this skill to design/update reusable test-case specs.
|
|
51
|
+
- `sdtk-qa` still owns release decision artifact (`QA_RELEASE_REPORT_*`).
|
|
52
|
+
|
|
53
|
+
## Notes
|
|
54
|
+
- This skill is for test-case specification artifacts, not test execution logs.
|
|
55
|
+
- For release approval and defect triage, continue with `sdtk-qa`.
|
|
56
|
+
|
|
57
|
+
## Validator Script
|
|
58
|
+
- `scripts/validate_test_case_spec.py`
|
|
59
|
+
|
|
60
|
+
### Typical command
|
|
61
|
+
```powershell
|
|
62
|
+
python "toolkit/skills/sdtk-test-case-spec/scripts/validate_test_case_spec.py" `
|
|
63
|
+
--file "docs/qa/[FEATURE_KEY]_TEST_CASE.md"
|
|
64
|
+
```
|
|
65
|
+
|
package/assets/toolkit/toolkit/skills/sdtk-test-case-spec/references/TEST_CASE_CREATION_RULES.md
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# TEST CASE CREATION RULES
|
|
2
|
+
## Canonical rules for `[FEATURE_KEY]_TEST_CASE.md`
|
|
3
|
+
|
|
4
|
+
**Version:** 1.0.0
|
|
5
|
+
**Last Updated:** 2026-02-25
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. Purpose
|
|
10
|
+
- Standardize creation of feature test-case documents in markdown.
|
|
11
|
+
- Mirror Excel-style worksheet layout while keeping output reviewable in `.md`.
|
|
12
|
+
- Keep QA artifacts reusable across projects, domains, and screen sets.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## 2. Output Contract
|
|
17
|
+
- Primary output file:
|
|
18
|
+
- `docs/qa/[FEATURE_KEY]_TEST_CASE.md`
|
|
19
|
+
- Optional language/project variant:
|
|
20
|
+
- `docs/en/qa/[FEATURE_KEY]_TEST_CASE.md` (only when the project explicitly uses `docs/en/**`).
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 3. Required Section Order
|
|
25
|
+
1. Document metadata (`Document ID`, `Version`, `Date`, `Author`, `Status`)
|
|
26
|
+
2. `Statistic Summary (Excel-aligned)`
|
|
27
|
+
3. `Abbreviations`
|
|
28
|
+
4. `1. Scope`
|
|
29
|
+
5. `2. References`
|
|
30
|
+
6. `3. Test Environment and Common Data`
|
|
31
|
+
7. `4. Feature Coverage Matrix`
|
|
32
|
+
8. `5. Screen-based Test Cases (Excel-aligned)`
|
|
33
|
+
9. `6. Open Questions (for final freeze)`
|
|
34
|
+
10. `7. STC/UAT Note`
|
|
35
|
+
|
|
36
|
+
Do not reorder these sections unless the user requests a different contract.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## 4. Statistic Summary Rules
|
|
41
|
+
- Place summary near the top of the file (before detailed UTC/ITC tables).
|
|
42
|
+
- Keep columns aligned with Excel `Statistic` logic:
|
|
43
|
+
- `Num of Case`
|
|
44
|
+
- `OK`
|
|
45
|
+
- `NG`
|
|
46
|
+
- `Not tested yet`
|
|
47
|
+
- `Done (%)`
|
|
48
|
+
- `Updated Date`
|
|
49
|
+
- Compute:
|
|
50
|
+
- `Not tested yet = Num of Case - (OK + NG)`
|
|
51
|
+
- `Done (%) = (OK + NG) / Num of Case`
|
|
52
|
+
- Include subtotal rows at minimum:
|
|
53
|
+
- `Unit Test Total`
|
|
54
|
+
- `Integration Test Total`
|
|
55
|
+
- `Grand Total`
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## 5. Screen-Based Worksheet Mapping
|
|
60
|
+
- Use `screen-first` layout to mirror Excel tabs:
|
|
61
|
+
- Each functional screen has a section (for example `SCH01`, `SCH02`, ...).
|
|
62
|
+
- Each screen section can have 2 sub-sections:
|
|
63
|
+
- `UTC` worksheet (name pattern: `[SCREEN_KEY]_UTC`)
|
|
64
|
+
- `ITC` worksheet (name pattern: `[SCREEN_KEY]_ITC`)
|
|
65
|
+
- Add one mapping table in section 5 that lists:
|
|
66
|
+
- `Screen`
|
|
67
|
+
- `Suggested Worksheet Pair`
|
|
68
|
+
- `UTC Cases`
|
|
69
|
+
- `ITC Cases`
|
|
70
|
+
- `Notes`
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## 6. Test Case Table Schema (Mandatory)
|
|
75
|
+
- Use one unified 18-column schema for both UTC and ITC tables:
|
|
76
|
+
- `No`
|
|
77
|
+
- `Test Type`
|
|
78
|
+
- `Test Perspective`
|
|
79
|
+
- `Test Item`
|
|
80
|
+
- `Precondition`
|
|
81
|
+
- `Test Steps`
|
|
82
|
+
- `Expected Result`
|
|
83
|
+
- `Browser`
|
|
84
|
+
- `Test Execution Result`
|
|
85
|
+
- `Remarks`
|
|
86
|
+
- `Reviewer`
|
|
87
|
+
- `Review Date`
|
|
88
|
+
- `OK/NG`
|
|
89
|
+
- `Cause`
|
|
90
|
+
- `Countermeasure`
|
|
91
|
+
- `Owner`
|
|
92
|
+
- `Completion Date`
|
|
93
|
+
- `Confirmation`
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## 7. Numbering and ID Policy
|
|
98
|
+
- Keep a stable `No` for each test case row.
|
|
99
|
+
- Do not renumber existing case IDs only for visual regrouping.
|
|
100
|
+
- In screen-split sections, case IDs may be non-contiguous; this is allowed.
|
|
101
|
+
- Summary/helper tables must keep contiguous `No` (`1,2,3,...`).
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## 8. Open Questions (OQ) Policy
|
|
106
|
+
- If expected behavior is unclear, create `OQ-xx` entries in section 6.
|
|
107
|
+
- Do not assume behavior for:
|
|
108
|
+
- permission matrix
|
|
109
|
+
- conflict dialog/action semantics
|
|
110
|
+
- API contract ambiguities
|
|
111
|
+
- release-scope boundary
|
|
112
|
+
- When resolved, keep question row and set status/remarks to resolved.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## 9. Language and Encoding
|
|
117
|
+
- Default artifact language: English.
|
|
118
|
+
- Keep original JP/VI labels when required by business/UI traceability (for example button labels).
|
|
119
|
+
- File encoding must be UTF-8.
|
|
120
|
+
- Avoid mojibake and placeholder tokens (`??`, `?????`) in final output.
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## 10. Final Validation Checklist
|
|
125
|
+
- Required sections exist and are in correct order.
|
|
126
|
+
- Statistic totals equal sum of UTC/ITC rows.
|
|
127
|
+
- Screen mapping table case counts match actual UTC/ITC table counts.
|
|
128
|
+
- Scope explicitly states in-scope and out-of-scope boundaries.
|
|
129
|
+
- Open questions are explicitly tracked with owner and impact.
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Lightweight validator for [FEATURE_KEY]_TEST_CASE.md
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
import argparse
|
|
9
|
+
import re
|
|
10
|
+
import sys
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
REQUIRED_HEADINGS = [
|
|
15
|
+
"## Statistic Summary (Excel-aligned)",
|
|
16
|
+
"## Abbreviations",
|
|
17
|
+
"## 1. Scope",
|
|
18
|
+
"## 2. References",
|
|
19
|
+
"## 3. Test Environment and Common Data",
|
|
20
|
+
"## 4. Feature Coverage Matrix",
|
|
21
|
+
"## 5. Screen-based Test Cases (Excel-aligned)",
|
|
22
|
+
"## 6. Open Questions (for final freeze)",
|
|
23
|
+
"## 7. STC/UAT Note",
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def has_18_columns(header_line: str) -> bool:
|
|
28
|
+
# markdown table columns = number of "|" minus 1 (leading/trailing)
|
|
29
|
+
pipe_count = header_line.count("|")
|
|
30
|
+
return pipe_count - 1 == 18
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def main() -> int:
|
|
34
|
+
parser = argparse.ArgumentParser(
|
|
35
|
+
description="Validate QA test-case markdown format for SDTK."
|
|
36
|
+
)
|
|
37
|
+
parser.add_argument(
|
|
38
|
+
"--file",
|
|
39
|
+
required=True,
|
|
40
|
+
help="Path to [FEATURE_KEY]_TEST_CASE.md",
|
|
41
|
+
)
|
|
42
|
+
args = parser.parse_args()
|
|
43
|
+
|
|
44
|
+
path = Path(args.file)
|
|
45
|
+
if not path.exists():
|
|
46
|
+
print(f"[FAIL] file not found: {path}")
|
|
47
|
+
return 1
|
|
48
|
+
|
|
49
|
+
text = path.read_text(encoding="utf-8")
|
|
50
|
+
lines = text.splitlines()
|
|
51
|
+
ok = True
|
|
52
|
+
|
|
53
|
+
for heading in REQUIRED_HEADINGS:
|
|
54
|
+
if heading not in text:
|
|
55
|
+
print(f"[FAIL] missing heading: {heading}")
|
|
56
|
+
ok = False
|
|
57
|
+
|
|
58
|
+
utc_sections = re.findall(r"^#### .*UTC.*$", text, flags=re.MULTILINE)
|
|
59
|
+
itc_sections = re.findall(r"^#### .*ITC.*$", text, flags=re.MULTILINE)
|
|
60
|
+
if not utc_sections:
|
|
61
|
+
print("[FAIL] no UTC subsection found")
|
|
62
|
+
ok = False
|
|
63
|
+
if not itc_sections:
|
|
64
|
+
print("[FAIL] no ITC subsection found")
|
|
65
|
+
ok = False
|
|
66
|
+
|
|
67
|
+
# Validate 18-column table headers for UTC/ITC tables
|
|
68
|
+
expected_header = (
|
|
69
|
+
"| No | Test Type | Test Perspective | Test Item | Precondition | Test Steps | "
|
|
70
|
+
"Expected Result | Browser | Test Execution Result | Remarks | Reviewer | "
|
|
71
|
+
"Review Date | OK/NG | Cause | Countermeasure | Owner | Completion Date | Confirmation |"
|
|
72
|
+
)
|
|
73
|
+
if expected_header not in text:
|
|
74
|
+
print("[FAIL] missing canonical 18-column test-case table header")
|
|
75
|
+
ok = False
|
|
76
|
+
else:
|
|
77
|
+
if not has_18_columns(expected_header):
|
|
78
|
+
print("[FAIL] canonical test-case table header column count is not 18")
|
|
79
|
+
ok = False
|
|
80
|
+
|
|
81
|
+
placeholders = []
|
|
82
|
+
for i, line in enumerate(lines, start=1):
|
|
83
|
+
if "??" in line or "?????" in line:
|
|
84
|
+
placeholders.append(i)
|
|
85
|
+
if placeholders:
|
|
86
|
+
print(f"[FAIL] unresolved placeholder tokens at lines: {placeholders[:20]}")
|
|
87
|
+
ok = False
|
|
88
|
+
|
|
89
|
+
if ok:
|
|
90
|
+
print("[PASS] test-case markdown format validation passed")
|
|
91
|
+
return 0
|
|
92
|
+
|
|
93
|
+
return 1
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
if __name__ == "__main__":
|
|
97
|
+
sys.exit(main())
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# QUALITY CHECKLIST
|
|
2
|
+
## Multi-Agent Development Pipeline Gates (v2.1 - 6 Phases)
|
|
3
|
+
|
|
4
|
+
**Current Feature:** `{{FEATURE_KEY}}`
|
|
5
|
+
**Last Updated:** `{{DATETIME}}`
|
|
6
|
+
**Overall Status:** `PHASE 1 PM INITIATION - IN PROGRESS`
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## PHASE 1: PM INITIATION (Project Kickoff) CHECKLIST
|
|
11
|
+
|
|
12
|
+
| # | Criteria | Status | Verified By | Notes/Issues | Date |
|
|
13
|
+
|---|----------|--------|-------------|--------------|------|
|
|
14
|
+
| 1 | Requirements received from stakeholders | [ ] Pending | PM Agent | | |
|
|
15
|
+
| 2 | Business problem clearly defined | [ ] Pending | PM Agent | | |
|
|
16
|
+
| 3 | High-level scope documented (REQ-xx) + Open Questions (OQ-xx) captured | [ ] Pending | PM Agent | | |
|
|
17
|
+
| 4 | Stakeholders identified | [ ] Pending | PM Agent | | |
|
|
18
|
+
| 5 | Success criteria defined (measurable) | [ ] Pending | PM Agent | | |
|
|
19
|
+
| **6** | **PM INITIATION COMPLETE** | [ ] Pending | **PM Gate** | **@ba please analyze** | |
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## PHASE 2: BA (Business Analysis) CHECKLIST
|
|
24
|
+
|
|
25
|
+
| # | Criteria | Status | Verified By | Notes/Issues | Date |
|
|
26
|
+
|---|----------|--------|-------------|--------------|------|
|
|
27
|
+
| 1 | Domain Glossary complete (all terms defined) | [ ] Pending | BA Agent | | |
|
|
28
|
+
| 2 | Business Rules numbered and complete (BR-01...) | [ ] Pending | BA Agent | | |
|
|
29
|
+
| 3 | Use Cases cover 100% requirements (UC-01...) | [ ] Pending | BA Agent | | |
|
|
30
|
+
| 4 | Data entities and relationships documented | [ ] Pending | BA Agent | | |
|
|
31
|
+
| 5 | Risks identified + prioritized (High/Med/Low) | [ ] Pending | BA Agent | | |
|
|
32
|
+
| 6 | Open questions listed for PM/ARCH review | [ ] Pending | BA Agent | | |
|
|
33
|
+
| **7** | **BA SPECS READY** | [ ] Pending | **BA Gate** | **@pm specs ready for PRD** | |
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## PHASE 2+: PM PLANNING CHECKLIST
|
|
38
|
+
|
|
39
|
+
| # | Criteria | Status | Verified By | Notes/Issues | Date |
|
|
40
|
+
|---|----------|--------|-------------|--------------|------|
|
|
41
|
+
| 1 | PRD aligns 100% with BA specs + resolves/records OQ decisions | [ ] Pending | PM Agent | | |
|
|
42
|
+
| 2 | Backlog 100% traceable to BA Use Cases | [ ] Pending | PM Agent | | |
|
|
43
|
+
| 3 | Story priorities reflect business value (MoSCoW) | [ ] Pending | PM Agent | | |
|
|
44
|
+
| 4 | Success metrics defined and measurable | [ ] Pending | PM Agent | | |
|
|
45
|
+
| 5 | Release criteria objective and testable | [ ] Pending | PM Agent | | |
|
|
46
|
+
| 6 | Effort estimates realistic (Fibonacci story points) | [ ] Pending | PM Agent | | |
|
|
47
|
+
| **7** | **PM BACKLOG READY** | [ ] Pending | **PM Gate** | **@arch please design** | |
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## PHASE 3: ARCH (Solution Architecture) CHECKLIST
|
|
52
|
+
|
|
53
|
+
| # | Criteria | Status | Verified By | Notes/Issues | Date |
|
|
54
|
+
|---|----------|--------|-------------|--------------|------|
|
|
55
|
+
| 1 | System architecture diagram complete + assumptions/OQ documented | [ ] Pending | ARCH Agent | | |
|
|
56
|
+
| 2 | Database schema/ERD documented + `DATABASE_SPEC_[FEATURE_KEY].md` updated (if DB scope) | [ ] Pending | ARCH Agent | | |
|
|
57
|
+
| 3 | API contract docs updated (`[FeaturePascal]_API.yaml` + `[FEATURE_KEY]_ENDPOINTS.md`) when API scope exists | [ ] Pending | ARCH Agent | | |
|
|
58
|
+
| 4 | API flow list updated (`[feature_snake]_api_flow_list.txt`) when API scope exists | [ ] Pending | ARCH Agent | | |
|
|
59
|
+
| 5 | API design detail updated (`[FEATURE_KEY]_API_DESIGN_DETAIL.md`) when API scope exists and mode is `auto/on` | [ ] Pending | ARCH Agent | Mode from `sdtk.config.json` | |
|
|
60
|
+
| 6 | Flow-action screen spec updated (`[FEATURE_KEY]_FLOW_ACTION_SPEC.md`) when UI flow scope exists | [ ] Pending | ARCH Agent | | |
|
|
61
|
+
| 7 | Screen layout spec updated (`DESIGN_LAYOUT_[FEATURE_KEY].md`) when UI scope exists | [ ] Pending | ARCH Agent | | |
|
|
62
|
+
| 8 | Security model documented (auth/authz) | [ ] Pending | ARCH Agent | | |
|
|
63
|
+
| **9** | **ARCH DESIGN READY** | [ ] Pending | **ARCH Gate** | **@dev please implement** | |
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## PHASE 4: DEV (Development + Code Review) CHECKLIST
|
|
68
|
+
|
|
69
|
+
| # | Criteria | Status | Verified By | Notes/Issues | Date |
|
|
70
|
+
|---|----------|--------|-------------|--------------|------|
|
|
71
|
+
| 1 | Implementation Plan matches ARCH design + backlog + clarifications logged (OQ-xx) | [ ] Pending | Dev Agent | | |
|
|
72
|
+
| 2 | **Unit Tests:** coverage meets target | [ ] Pending | Dev Agent | | |
|
|
73
|
+
| 3 | **Integration Tests:** critical flows covered | [ ] Pending | Dev Agent | | |
|
|
74
|
+
| 4 | Linting and type checking passes | [ ] Pending | Dev Agent | | |
|
|
75
|
+
| 5 | Security checklist passed | [ ] Pending | Dev Agent | | |
|
|
76
|
+
| 6 | Performance baseline established | [ ] Pending | Dev Agent | | |
|
|
77
|
+
| 7 | **Self Code Review:** Complete | [ ] Pending | Dev Agent | MANDATORY | |
|
|
78
|
+
| 8 | **Peer Code Review:** Requested | [ ] Pending | Dev Agent | MANDATORY (AI allowed) | |
|
|
79
|
+
| 9 | **Peer Code Review:** All comments addressed | [ ] Pending | Dev Agent | MANDATORY (AI allowed) | |
|
|
80
|
+
| **10** | **DEV READY FOR QA** | [ ] Pending | **Dev Gate** | **Code Review [x] then @qa please test** | |
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## PHASE 5: QA (Quality Assurance) CHECKLIST
|
|
85
|
+
|
|
86
|
+
| # | Criteria | Status | Verified By | Notes/Issues | Date |
|
|
87
|
+
|---|----------|--------|-------------|--------------|------|
|
|
88
|
+
| 1 | Test Strategy covers all critical paths + unclear ACs escalated (OQ-xx) | [ ] Pending | QA Agent | | |
|
|
89
|
+
| 2 | Test case specification updated (`[FEATURE_KEY]_TEST_CASE.md`) when detailed test design scope exists | [ ] Pending | QA Agent | | |
|
|
90
|
+
| 3 | **E2E Tests:** P1 flows PASS (if applicable) | [ ] Pending | QA Agent | | |
|
|
91
|
+
| 4 | **Defects:** 0 HIGH severity open | [ ] Pending | QA Agent | | |
|
|
92
|
+
| 5 | **Coverage:** meets targets | [ ] Pending | QA Agent | | |
|
|
93
|
+
| 6 | No flaky tests | [ ] Pending | QA Agent | | |
|
|
94
|
+
| 7 | Performance meets NFRs | [ ] Pending | QA Agent | | |
|
|
95
|
+
| 8 | Release Report complete | [ ] Pending | QA Agent | | |
|
|
96
|
+
| **9** | **QA APPROVED** | [ ] Pending | **QA Gate** | **@pm please finalize release status** | |
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## PHASE 6: PM CLOSURE CHECKLIST
|
|
101
|
+
|
|
102
|
+
| # | Criteria | Status | Verified By | Notes/Issues | Date |
|
|
103
|
+
|---|----------|--------|-------------|--------------|------|
|
|
104
|
+
| 1 | QA release decision reviewed by PM | [ ] Pending | PM Agent | | |
|
|
105
|
+
| 2 | Outstanding OQ/risks triaged for next iteration | [ ] Pending | PM Agent | | |
|
|
106
|
+
| 3 | Final status communicated to stakeholders | [ ] Pending | PM Agent | | |
|
|
107
|
+
| **4** | **FEATURE CLOSURE COMPLETE** | [ ] Pending | **PM Gate** | **Pipeline complete** | |
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## FINAL RELEASE GATE
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
RELEASE STATUS: IN PROGRESS
|
|
115
|
+
|
|
116
|
+
FINAL VERIFICATION:
|
|
117
|
+
[ ] Phase 1 PM Init
|
|
118
|
+
[ ] Phase 2 BA
|
|
119
|
+
[ ] Phase 2+ PM Plan
|
|
120
|
+
[ ] Phase 3 ARCH
|
|
121
|
+
[ ] Phase 4 DEV + Code Review
|
|
122
|
+
[ ] Phase 5 QA
|
|
123
|
+
[ ] Phase 6 PM Closure
|
|
124
|
+
```
|